初始化实例字段与本地variables

我一直想知道为什么在下面的例子中, 不要初始化实例字段(依靠它将有它的默认值)并访问它,而局部variables显然必须被初始化,即使我初始化为默认值它会得到反正…

public class TestClass { private bool a; public void Do() { bool b; // That would solve the problem: = false; Console.WriteLine(a); Console.WriteLine(b); //Use of unassigned local variable 'b' } } 

对于局部variables,编译器有一个stream程的好主意 – 它可以看到variables的“读取”和variables的“写入”,并certificate(在大多数情况下)第一次写入会在第一次读取之前发生。

实例variables不是这种情况。 考虑一个简单的属性 – 你怎么知道是否有人将它设置之前,他们得到它? 这使得执行明智的规则基本上是不可行的 – 所以要么必须确保所有的字段都在构造函数中设置,或者让它们具有默认值。 C#团队select了后一种策略。

它受C#中的明确赋值规则的控制。 variables在访问前必须明确分配。

5.3明确的分配

在函数成员的可执行代码的给定位置,如果编译器可以通过特定的静态stream分析(§5.3.3)certificatevariables已被自动初始化或已经被至less一个任务的目标。

5.3.1最初分配的variables

以下类别的variables被分类为初始分配:

  • 静态variables。

  • 类实例的实例variables。

  • 最初分配的结构variables的实例variables。

  • 数组元素。

  • 值参数。

  • 参考参数。

  • 在catch子句或foreach语句中声明的variables。

5.3.2最初未分配的variables

以下类别的variables被分类为初始未分配:

  • 最初未分配的结构体variables的实例variables。

  • 输出参数,包括结构实例构造函数的这个variables。

  • 局部variables,除了在catch子句或foreach语句中声明的variables。

当一个内存块被分配给一个新的对象实例时,运行时在整个块上写零,确保新对象以已知状态启动 – 这就是为什么整数缺省为0,缺省值为0.0,指针和对象引用归零,依此类推。

理论上讲,也可以做同样的事情来堆栈分配作为方法调用的一部分的帧。 开销,虽然会很高 – 这将大大减慢调用其他方法,因此不尝试。

实例variables有一个默认值。 从C#3.0规范:

5.1.2.1类中的实例variables

一个类的实例variables在创build该类的新实例时出现,并且在没有对该实例的引用以及实例的终结器(如果有)已经执行时停止存在。

类的实例variables的初始值是variablestypes的默认值(第5.2节)。

为了进行明确的分配检查,实例variables被认为是初始分配的。

这是一个编译器限制。 编译器试图阻止你在任何地方使用一个未分配的variables,这是一件好事,因为使用未初始化的variables曾经是旧C代码中常见的错误来源。

编译器不能知道实例variables是否在你打这个方法调用之前被初始化,因为它可以通过任何其他的方法来设置,这个方法可以被外部代码以任何顺序调用。

隐含的构造函数为你初始化实例variables。 即使你指定了一个c'tor,但是不要初始化一个字段,它也是在堆上创build对象的一部分。 堆栈局部variables不是这样。

这只是一个警告能告诉你的问题。 警告确实没有办法确保其他方法没有初始化类variables,所以它只警告它可以确定的那个不会被初始化。

此外,这是一个警告,而不是一个错误,因为使用未分配的variables没有任何技术上的错误(它保证是'假'),但它可能是一个逻辑错误,让它取消分配。