繁体   English   中英

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

[英]Why must local variables have initial values?

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

int test1; // Not initialized, but OK

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

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

字段自动初始化为类型的逻辑零; 这是隐含的。 变量必须服从“明确赋值”,所以必须在它们被读取之前赋值。

ECMA 334v4

§17.4.4 字段初始化

字段的初始值,无论是静态字段还是实例字段,都是字段类型的默认值(第 12.2 节)。 在此默认初始化发生之前无法观察字段的值,因此字段永远不会“未初始化”。

第 12 条。 变量

... 变量在获得其值之前应明确分配(第 12.3 节)。 ...

延伸马克的回答,局部变量初始化也与验证过程有关

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

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

根据微软的说法(同样,由Eric Lippert在回答他博客上的一个问题时支持),在大多数情况下,当程序员不初始化他们的局部变量时,他们不会这样做,因为他们依赖底层环境来初始化他们的变量为默认值,但只是因为他们“忘记”了,因此,有时会导致错觉的逻辑错误。

因此,为了减少这种性质的错误出现在 C# 代码中的可能性,编译器仍然坚持您将初始化您的局部变量。 即使它将.locals init标志添加到生成的CIL代码中。

关于这个主题的更全面的解释可以在这里找到: Behind The .locals init Flag

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

编译器在这里为您提供帮助。

所以不要将它们初始化为一种习惯。 而是让编译器帮助您!

这样做的好处是它会为您进行路径检查。 如果您有一个包含三种情况的 switch 语句,其中每种情况都设置了值,但您忘记在“默认”中设置它,但之后使用它,它会警告您错过了一条路径。

如果你将变量初始化为= 0 ,你就会失去这个好处。

正如 Marc 所指出的,这就是规范所说的。 这是一件好事的原因是,有一些正当的理由让成员未初始化而不是局部变量,其生命周期受其所在方法的限制。大多数情况下,出于性能原因,您只需要这样做,如果变量初始化成本高,应该只在特定的使用场景下初始化。 就我而言,我会避免使用未初始化的成员,直到我真正靠在墙上为止!

对于局部变量,检测是否所有代码路径都可能导致初始化也容易得多,而没有很好的启发式方法来确定整个程序中的所有代码路径是否都保证在使用前初始化。 所有计算机科学专业的学生都应该知道,在这两种情况下不可能有完全正确的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM