我注意到 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
中的 private string s
下划线并带有警告,表示“Field 'Foo.s' is never assigned to, and will always have its default value null
”。
现在,如果 VS 那么聪明并且知道 s 将始终为 null,那么为什么在第二个示例中获取它的长度不是错误呢?我最初的猜测是,“如果编译器根本无法完成其工作,它只会给出编译错误。从技术上讲,只要您从不调用 Bar(),代码就会运行,所以它只是一个警告。”但第一个示例的解释无效。只要您从不调用 Bar(),您仍然可以运行代码而不会出现错误。那么什么给出呢?只是一个疏忽,还是我错过了什么?
第一个示例(错误)是编译器的“定义赋值”跟踪的示例,仅适用于局部变量。由于上下文有限,编译器对这种情况有严密的控制。请注意,s
不为空,它是未定义的。
在第二个示例中,
s
是一个字段(默认为 null)。没有编译器错误,但总是会在运行时捕获。 这种特殊情况可能会被捕获,但编译器通常无法检测到这种错误。
例如,您可以添加一个方法
Bar2()
s
,但晚于 Bar()
调用它,或者根本不调用它。这将消除警告,但不会消除运行时错误。所以这是设计使然。
编译器并非100%正确。 如果通过反射修改实例,“s”可能具有非空值。
是一个局部变量,编译器可以轻松检查s变量在使用之前是否未被分配。 在第二个中,
s是一个全局变量,它可能是在类中的其他地方初始化的。