似乎无法在代码中使用未分配的局部变量或检查它们,因为编译器会发出Use of unassigned local variable
错误。
为什么编译器在编译时没有对这些变量使用default(T)
?
即使对值类型更难做,在这种情况下,引用类型可以很容易地初始化为null
,对吗?
以下是一些测试代码:
public void Test ( )
{
int x;
string s;
if ( x == 5 )
Console.WriteLine ( 5 );
if ( s != null )
Console.WriteLine ( "s" );
}
返回:
Use of unassigned local variable 'x'
Use of unassigned local variable 's'
更新:
对于那些声称这是不允许有充分理由的人,为什么在课堂上允许这样做?
public class C
{
public int X;
public string S;
public void Print ( )
{
Console.WriteLine ( X );
Console.WriteLine ( S );
}
}
此代码编译完全正常。
为什么在课程级别而不是在方法级别上没有问题?
答案 0 :(得分:6)
C#是一种“成功之坑”的语言。
这是一个设计决策,因为该语言完全能够允许您使用未明确分配的本地语言。但是,通常情况下,这些变量的使用是错误的,代码路径由于某种原因没有设置值。为避免此类错误,编译器要求在使用之前分配所有本地文件。
答案 1 :(得分:6)
我看到你已经更新了你的问题,所以我会更新我的答案。您的问题分为两部分,一部分与local variables
相关,另一部分与instance variables on a class instance
相关。首先,这不是一个真正的编译器设计决策,而是一个语言设计决策。
Spec第12.3.1 / 12.3.2节
我们知道为什么你可以定义一个变量而不给它一个值。一个原因,例如:
int x;
// do stuff
x = 5; // Wow, I can initialize it later!
Console.WriteLine(x);
标准定义了这是有效代码的原因。现在,我不是在C#设计团队,但很有道理他们为什么不会自动为你初始化代码(除了你实际没有希望它是自动初始化)。
说上面的代码是您的意图,但您忘记初始化x = 5;
。如果编译器已经为你自动初始化了变量,代码就会编译,但它会像你期望的那样做。
虽然这是一个简单的例子,但这是来自语言设计者的非常好的设计决策,因为它可以避免许多令人头疼的问题,试图弄清楚为什么某些东西没有按预期工作。
作为旁注,我想不出你为什么要在没有分配内容的情况下定义代码的原因,或者使用默认值(在每种情况下),对我来说可能是一个bug,我确信编译器设计师可能已经确定了这一点。
班级成员由最初分配的标准定义。实际上,公平地说,在catch
,foreach
或using
语句中声明的局部变量最初是未分配的。实际上,这是一个标准问题,而不是编译器问题。
如果我试图猜测为什么这是关于类实例的实例变量的情况,我会说它与如何在堆上分配内存有关,因为那是分配类的地方。在堆上分配类时,必须初始化所有成员并在堆上分配它。在类成员而不是局部变量中执行它不仅可以,它以方式完成。他们只是不能保持未分配状态。
答案 2 :(得分:5)
1为什么编译器不允许使用未初始化的变量?
因为防止促进良好的编程。
2为什么编译器允许使用未初始化的类成员?
因为无法准确跟踪此信息。
答案 3 :(得分:1)
通过将您的引用类型初始化为null的建议,而不是当前行为(错误代码导致编译时错误),当您取消引用未初始化的变量时,您将获得运行时错误。这真的是你想要的吗?
答案 4 :(得分:0)
请考虑以下代码:
void blah(IDictionary<int,int> dict)
{
for (int i=0; i<10; i++)
{
if ((i & 11) != 0)
{
int j;
dict.TryGetValue(i, out j);
System.Diagnostics.Debug.Print("{0}",j);
j++;
}
}
}
假设传递的TryGetValue
实现的IDictionary<int,int>
方法实际上从未写入j
[如果用C#编写,则不可能,但如果用其他语言编写则可能]。应该期望代码打印什么?
C#标准中没有任何内容要求在代码离开j
语句时保留if
,但没有任何要求在循环迭代之间将其重置为零。在某些情况下,强制采取任何行动都会产生额外费用。标准只允许在TryGetValue
被调用时,j
可以任意保持零或它在范围内时持有的最后一个值,而不是两者之一。这种方法避免了不必要的成本,但如果允许代码在重新进入作用域和写入时间之间看到j
的值(将未初始化的变量作为{{用其他语言编写的代码的{1}}参数会暴露其值可能是无意的)。
答案 5 :(得分:-1)
因为你想要什么?你希望x默认为零,我希望它是5 ...
如果他们为int(s)分配0并且所有世界都开始假设,那么它们将在某个时刻变为-1,这将打破全球许多应用程序。
我认为VB6变量中的默认分配给某些东西,并且它看起来并不像看起来那么好。
当您使用C#或C ++时,您可以根据需要分配值,而不是编译器。