5

我注意到 Visual Studio 有一些特别之处。首先,尝试在函数的某处键入此(C#):

class Foo  
{  
    public void Bar()  
    {  
        string s;
        int i = s.Length;
    }
}

现在,它会立即将sin标记s.Length为错误,并说“ Use of unassigned local variable 's'”。另一方面,试试这个代码:

class Foo  
{  
    private string s;
    public void Bar()  
    {  
        int i = s.Length;
    }
}

它将编译,并用警告在sin下划线private string s,说“ Field 'Foo.s' is never assigned to, and will always have its default value null”。

现在,如果 VS 很聪明并且知道 s 将始终为空,为什么在第二个示例中获取它的长度不是错误?我最初的猜测是,“如果编译器根本无法完成它的工作,它只会给出一个编译错误。因为从技术上讲,只要你从不调用 Bar(),代码就会运行,这只是一个警告。” 除了解释被第一个例子无效。只要您从不调用 Bar(),您仍然可以运行代码而不会出错。那么给了什么?只是一个疏忽,还是我错过了什么?

4

4 回答 4

8

第一个示例(错误)是编译器明确赋值跟踪的示例,仅适用于局部变量。由于上下文有限,编译器对这种情况有一个严密的控制。请注意,s它不是 null,它是未定义的。

在第二个示例中,s是一个字段(默认为空)。没有编译器错误,但它总是会在运行时被捕获。这种特殊情况可能会被捕获,但编译器通常无法检测到这种错误。
例如,您可以添加一个方法Bar2(),该方法将字符串分配给s但在 之后调用它Bar(),或者根本不调用它。这将消除警告,但不会消除运行时错误。

所以这是设计使然。

于 2009-09-11T20:58:05.007 回答
3

对于第二个示例,代码有效,但可能无法正确运行。以下是该程序可以“成功”执行的几种情况

  • 编译器不是 100% 正确的。如果通过反射修改实例,则“s”可能具有非空值。
  • 如果从未调用方法 Bar ,程序可以正常执行
  • 这个程序可能是一个测试程序,它出于测试原因触发了 NullReferenceException
于 2009-09-12T09:45:53.773 回答
0

我能做出的唯一猜测是,在第二个示例中,可以通过反射更改 s(使用 BindingFlags.Private 访问私有成员)。

于 2009-09-11T20:59:12.263 回答
0

在第一个示例中,s是一个局部变量,编译器可以很容易地检查s变量在使用之前是否未分配。

在第二个中,s是一个全局变量,它可能是在类的其他地方初始化的。

于 2009-09-11T21:01:40.330 回答