在 C# 中,如果我执行以下操作:
int x;
然后按 F10,我看到 x 中存储了一个零。
但是当我尝试使用 x 时,它告诉我应该初始化它.. 为什么会这样?那里应该是零,对吧?
数组也是如此,所以:
int[]a = new int[5];
如果我们按 F10,我们会看到里面的所有整数都是零。
这是怎么回事 ?为什么我必须在 C# 中初始化一个变量,这与在 C++ 中不同?
这是一个编译时错误,试图帮助您减少由于未初始化变量而导致的代码错误。很有用。
http://msdn.microsoft.com/en-us/library/4y7h161d(VS.80).aspx
更多阅读:
http://blogs.msdn.com/b/abhinaba/archive/2005/11/08/490248.aspx
关于禁用错误的一些话(你不能只是警告你 - 这不是警告):
和
http://blogs.msdn.com/b/ericlippert/archive/2009/10/12/absence-of-evidence-is-not-evidence-of-absence.aspx (证明是关于这个主题的最丰富的信息)
甚至更多讨论“localsinit” IL 标志(强制为本地设置默认值)与其与“双重赋值”的关系(C# 强制您编写int v=0
,即使它已经存在)之间的关系。如果您想更深入地阅读 - ECMA-335 的第 I.12.2 节中定义的“localsinit”,请点击此处。
简单地说,因为这就是 C# 的工作方式。来自 C# 语言规范:
5.3.2 最初未赋值的变量
以下类别的变量被归类为最初未分配:
· 最初未分配的结构变量的实例变量。
·输出参数,包括struct实例构造函数的this变量。
· 局部变量,在 catch 子句或 foreach 语句中声明的变量除外。
另一方面:
5.3.1 初始赋值变量
以下类别的变量被归类为最初指定的:
· 静态变量。
· 类实例的实例变量。
· 最初分配的结构变量的实例变量。
· 数组元素。
· 值参数。
· 参考参数。
· 在 catch 子句或 foreach 语句中声明的变量。
很简单……因为编译器坚持在使用局部变量之前先对其进行初始化。这可以防止与初始化失败相关的一整类错误。
如果您查看从以下几条语句生成的 IL:
int x;
Console.WriteLine("hello");
int y=5;
x=6;
Console.WriteLine(x+y);
您会看到以下内容:
//notice no ops related to x prior to console.writeline
IL_0000: ldstr "hello"
IL_0005: call System.Console.WriteLine
IL_000A: ldc.i4.5
IL_000B: stloc.1 //create/store y
IL_000C: ldc.i4.6
IL_000D: stloc.0 //x is really only created right here
IL_000E: ldloc.0
IL_000F: ldloc.1
IL_0010: add
IL_0011: call System.Console.WriteLine
如果您在将 x 存储到 IL 之前看到它的值,那么这是一个调试器技巧。
我相信自动初始化是一种运行时安全功能,而不是语言保证。碰巧.NET 会将变量归零,但这并不一定适用于每个框架。
请注意,对于数组,它是有保证的。
它为 0 只是运气,它可以是任何东西,这就是为什么你必须初始化它。