我注意到Visual Studio特有的一些东西。首先,尝试在函数中的某处键入此(C#):
class Foo
{
public void Bar()
{
string s;
int i = s.Length;
}
}
现在,它会立即将s
中的s.Length
标记为错误,并说“Use of unassigned local variable 's'
”。另一方面,请尝试以下代码:
class Foo
{
private string s;
public void Bar()
{
int i = s.Length;
}
}
它会进行编译,并在s
的{{1}}下方加上警告,并提示“private string s
”。
现在,如果VS很聪明并且知道s将始终为null,为什么在第二个示例中获取其长度不是错误?我最初的猜测是,“如果编译器根本无法完成其工作,它只会产生编译错误。由于代码在技术上运行只要你从不调用Bar(),它只是一个警告。”除非第一个例子使解释无效。只要你从不调用Bar(),你仍然可以毫无错误地运行代码。什么给出了什么?只是疏忽,还是我错过了什么?
答案 0 :(得分:8)
第一个示例(错误)是编译器definite-assignment跟踪的示例,仅适用于局部变量。由于上下文有限,编译器对这种情况有一个密不透风的掌握。请注意,s
不为空,未定义。
在第二个示例中,s
是一个字段(默认为null)。没有编译器错误,但它将始终在运行时捕获。这种特殊情况可能会被困住,但编译器通常无法检测到这种错误
例如,您可以添加一个方法Bar2()
,该方法会将字符串分配给s
,但会在Bar()
之后调用,或者根本不调用。{{1}}。这将消除警告,但不会消除运行时错误。
所以它是设计的。
答案 1 :(得分:3)
对于第二个示例,代码有效,它可能无法正常运行。以下是该程序可以“成功”执行的几种情况
答案 2 :(得分:0)
我唯一猜到的是,在第二个例子中,s可以通过反射来改变(使用BindingFlags.Private来访问私有成员)。
答案 3 :(得分:0)
在第一个示例中, s 是一个局部变量,编译器可以在使用之前轻松检查 s varible是否已分配。
在第二个中, s 是一个全局变量,它可能是在类的其他地方初始化的。