我是否可以在初始化整数变量时采用下列方式的任意一种?
int i = 0;
int i;
编译器或CLR是否将它们视为相同的东西?如果我没记错,它们应该被视为相同的东西,但我似乎找不到这篇文章了。
我是否可以在初始化整数变量时采用下列方式的任意一种?
int i = 0;
int i;
编译器或CLR是否将它们视为相同的东西?如果我没记错,它们应该被视为相同的东西,但我似乎找不到这篇文章了。
class Program
{
static void Main(string[] args)
{
intTest it;
it = new intTest();
Console.ReadLine();
}
class intTest
{
int i;
public intTest()
{
int i2;
Console.WriteLine("i = " + i);
Console.WriteLine("i2 = " + i2);
}
}
}
上述代码无法编译是因为 i2 没有被赋值。但是,通过将 i2 赋值为 0,即
int i2 = 0;
编译并运行后,将会显示它们现在都被赋值为0。
我查看了IL(使用ildasm),事实上只有在构造函数中将int设置为0才真正设置为0。
public class Class1
{
int setToZero = 0;
int notSet;
}
生成:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: stfld int32 ClassLibrary1.Class1::setToZero
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib]System.Object::.ctor()
IL_000d: nop
IL_000e: ret
} // end of method Class1::.ctor
在所有这些讨论中,值得一提的是C#中的"default"关键字。
即int i;
等同于int i = default(int);
,也等同于int i = 0;
和MyClass o = default(MyClass);
等同于MyClass o = null;
当使用linq方法如.SingleOrDefault()
时,这尤其重要,因为您可以始终使用以下内容使您的代码更易读:
int someValue = collection.<various linq methods>.SingleOrDefault();
if (someValue == default(int))
{
//Code for the default case
}
并且
MyClass someValue = collection.<various linq methods>.SingleOrDefault();
if (someValue == default(MyClass))
{
//Code for the default case
}
这里有一些回答是有误导性的,包括“Coding Horror”网站引用的文章。
当编译器配置为优化生成的代码时,编译器将优化您的代码以删除所有“不必要”的初始化。请注意,在“发布”模式下编译时,这是默认行为。
就我个人而言,我认为始终初始化所有变量非常有用。在调试模式下,性能损失很小,在发布模式下则没有损失,但对于将来维护代码的人而言,显式设置变量的收益将是巨大的,这是更好的“用代码记录代码”的风格。我记得我的一位经验丰富的同事认为Int32的默认值是Int32.MinValue而不是0。这种混乱总是会发生在代码中隐含的事物上,对我而言,它们在大多数情况下应该被避免。
正如以下链接所述,它们完全相同:
http://msdn.microsoft.com/en-us/library/aa664742%28VS.71%29.aspx
MyClass class;
MyClass class2 = null;
在值类型中(任何结构体,包括int / float / double等),类型会带着零传递,因此以下操作是等效的:
int i;
int j = 0;
然而,在一个方法中,编译器会检查你是否在使用类型之前为其赋值。如果你做了以下操作,编译器会报错:
int i;
Console.WriteLine{"{0}",i);
从技术上讲,上述代码应该是没有问题的 - 但由于这是程序员常见的错误之一,编译器会特别检查未赋值的本地变量并报错。然而,这只是一个编译时的问题,而不是CLR的问题。你可以生成执行上述操作的IL代码,它也能正常运行。
这些仅适用于字段(类变量)的等效。当类被初始化时,字段会自动分配默认值。在方法或属性内,未赋值的变量仍然保持未赋值状态,如果您尝试访问它的值,将会导致编译器错误。