为什么局部变量必须具有初始值

时间:2009-04-15 19:57:56

标签: c#

为什么我必须在方法中初始化变量?

int test1; // Not initialized, but ok

public int Foo()
{
   int test2;                 // Not initialized

   int test3 = test1;         // Ok
   int test4 = test2;         // An error
}

4 个答案:

答案 0 :(得分:15)

字段会自动初始化为类型的逻辑0;这是隐含的。变量必须服从“明确赋值”,因此必须才能被分配才能被读取。

ECMA 334v4

  

§17.4.4字段初始化

     

字段的初始值,是否   它是一个静态字段或实例   field,是默认值(第12.2节)   该字段的类型。这不可能   观察之前的一个字段的价值   这个默认初始化有   发生了,因此一个领域永远不会发生   “未初始化的”。

  

§12。变量

     

...   变量应在其之前明确赋值(第12.3节)   可以获得价值。   ...

答案 1 :(得分:12)

扩展Mark的答案,局部变量初始化也与验证过程有关 CLI要求在任何可验证的代码中(即,未使用SecurityPermission属性中的SkipVerfication属性明确要求跳过验证过程的模块),必须在使用之前初始化所有局部变量。如果不这样做,将导致VerficationException被抛出。

更有趣的是,编译器会自动在每个使用局部变量的方法上添加.locals init标志。此标志使JIT编译器生成将所有局部变量初始化为其默认值的代码。这意味着,即使您已经在自己的代码中初始化它们,JIT也将遵循.locals init标志并生成正确的初始化代码。这种“重复初始化”不会影响性能,因为在允许优化的配置中,JIT编译器将检测到重复并有效地将其视为“死代码”(自动生成的初始化例程不会出现在生成的汇编程序指令中)。

根据微软(也是由Eric Lippert在他的博客上回答问题的支持),在大多数情况下,当程序员没有初始化他们的局部变量时,他们不这样做,因为他们在底层传递环境将他们的变量初始化为默认值,但这只是因为他们“忘记”,因此导致有时虚幻的逻辑错误。
因此,为了减少这种性质的错误出现在C#代码中的可能性,编译器仍然坚持要初始化本地变量。即使它会将.locals init标志添加到生成的IL代码中。

有关此主题的更全面的解释,请访问:Behind The .locals init Flag

答案 2 :(得分:4)

实际上不应该。您的错误应该在第二行,而不是第一行,应该是因为您在初始化之前使用了它。

编译器在这里帮助你。

所以不要将它们初始化为习惯,而是让编译器帮助你!

关于这一点的好处是它会为你检查路径。如果你有一个switch语句有3个案例,每个案例都设置了值,但是你忘了将它设置为“默认”,但之后使用它会警告你错过了一个路径。

如果将变量初始化为= 0,则可以获得该利益。

答案 3 :(得分:2)

正如马克所说,这就是规范所说的。这是一个好东西的原因是有一些正当理由让成员未初始化而不是局部变量,其生命周期受其所处方法的限制。大多数情况下,你只是出于性能原因而想要这个,如果变量的初始化成本很高,只应在特定的使用场景下初始化。就我而言,我会避免未初始化的成员,直到我的背部真的靠墙而已!

对于局部变量,检测所有代码路径是否可能导致初始化也更容易,而没有良好的启发式方法来确定整个程序中的所有代码路径是否在使用前保证初始化。一个完全正确的答案是impossible in both cases,因为所有的CS学生都应该知道。