C#中的非初始化变量

我有以下代码:

class Foo { public Foo() { Bar bar; if (null == bar) { } } } class Bar { } 

代码专家已经看到这会给出错误。 在if语句之前可能没有初始化Bar。

所以现在我想知道:酒吧的价值是什么,不应该是空的吗? 它们不是设置为空吗? (空指针?)

不,局部变量没有默认值1 。 在阅读之前必须明确指定它们。 这样可以降低你使用你认为已经给出合理值的变量的可能性,实际上它有一些默认值。 这不能用于实例或静态变量,因为您不知道将调用方法的顺序。

有关明确赋值的更多详细信息,请参见C#3.0规范的第5.3节。

请注意,这与作为引用类型变量无关。 这将无法以相同的方式编译:

 int i; if (i == 0) // Nope, i isn't definitely assigned { } 

1就语言而言,无论如何……显然存储器中的存储位置有一些东西 ,但它是无关紧要的和特定于实现的。 有一种方法可以找出该值是什么,通过创建一个带out参数的方法,然后使用IL来查看方法中该参数的值,而不给它另一个值。 CLR根本不介意。 然后,您可以调用该方法传入一个非明确赋值的变量,并且看到您可以检测到该值 – 这可能基本上是“全零”值。

我怀疑CLI规范确实强制执行具有默认值的局部变量 – 但我必须检查。 除非你正在做上述的邪恶事情,否则在C#中对你来说无关紧要。

字段(类/结构上的变量)初始化为null / zero / etc. 局部变量……好 – 因为(通过“明确的分配”)你不能在没有分配的情况下访问它们,没有明智的回答方式; 简单地说,它没有被定义,因为它是不可能的。 我相信它们恰好null / zero / etc(可以通过动态IL生成来破解一些代码),但这是一个实现细节。


有关信息,这里有一些狡猾的代码,显示了一个正式未初始化的变量的值:

 using System; using System.Reflection.Emit; static class Program { delegate void Evil(out T value); static void Main() { MakeTheStackFilthy(); Test(); } static void Test() { int i; DynamicMethod mthd = new DynamicMethod("Evil", null, new Type[] { typeof(int).MakeByRefType()}); mthd.GetILGenerator().Emit(OpCodes.Ret); // just return; no assignments Evil evil = (Evil)mthd.CreateDelegate(typeof(Evil)); evil(out i); Console.WriteLine(i); } static void MakeTheStackFilthy() { DateTime foo = new DateTime(); Bar(ref foo); Console.WriteLine(foo); } static void Bar(ref DateTime foo) { foo = foo.AddDays(1); } } 

IL 只是做了“退缩” – 它从不分配任何东西。

不会为局部变量分配默认值。 您必须在使用它们之前初始化它们。 您可以明确地初始化为null

 public Foo() { Bar bar = null; if (null == bar) { } } 

局部变量未分配默认值,甚至不为null

不,局部变量不会自动设置为0(默认值)。

但是因为你(总是)得到那个错误,所以无所谓。 如果它有另一个值,编译器永远不会让你发现。

不要与字段变量(类成员)混淆,它们初始化为其类型的默认值(0 / null / false / …)。

bar的值未定义。 在堆栈上为它分配了空间,但是空间没有初始化为任何值,因此它包含之前碰巧存在的任何内容。

(但是局部变量可能会被优化为使用寄存器而不是堆栈空间,但它仍未定义。)

编译器不允许您使用未定义的值,它必须能够在您使用它之前确定变量已初始化。

作为比较,VB确实初始化局部变量。 虽然这有时是实用的,但它也意味着你在给它一个有意义的值之前无意间使用变量,并且编译器无法确定它是否是你所做的。

这没关系,因为任何实现C#的编译器都不应该编译这样的代码。

如果有默认值,那么它将是可编译的。 但是局部变量没有。

除“正确性”外,局部变量初始化还与CLR的validation过程有关
有关更多详细信息,请参阅我对此类似问题的回答: 为什么局部变量必须具有初始值