Visual Studio null引用警告 – 为什么没有错误?

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

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

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

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

它将编译,并在带有警告的private string ss加下划线,称“ 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()不是Bar() ,或者根本不调用它。 这将消除警告,但不会消除运行时错误。

所以它是设计的。

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

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

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

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

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