我注意到 Visual Studio 的一些特殊之处。首先,尝试在函数中的某个位置键入以下内容 (C#):

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

现在,它会立即标记 ss.Length 作为一个错误,说“Use of unassigned local variable 's'”。另一方面,尝试以下代码:

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

它将编译,并强调 sprivate string s 并发出警告,说“Field 'Foo.s' is never assigned to, and will always have its default value null".

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

有帮助吗?

解决方案

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

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

所以它是设计的。

其他提示

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

  • 编译器并非100%正确。如果通过反射修改实例,“s”可能具有非空值。
  • 如果从未调用过 Bar 方法,则程序可以无错误地执行
  • 该程序可能是一个测试程序,出于测试原因触发 NullReferenceException

我唯一猜到的是,在第二个例子中,s可以通过反射来改变(使用BindingFlags.Private来访问私有成员)。

在第一个示例中, s 是一个局部变量,编译器可以在使用之前轻松检查 s 变量是否已分配。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top