5

我注意到了一些关于Visual Studio的特殊情况。首先,尝试在功能的地方打字(C#):Visual Studio空引用警告 - 为什么没有错误?

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将始终为空,那么为什么在第二个示例中获得其长度并不是错误?我最初的猜测是,“如果编译器不能完成它的工作,它只会产生编译错误,因为只要你从不调用Bar(),代码在技术上运行,它只是一个警告。”除了第一个例子解释失效之外。只要你永远不会调用Bar(),你仍然可以无错地运行代码。那么是什么给了?只是疏忽,还是我错过了什么?

回答

8

第一个示例(错误)是编译器的definite-assignment跟踪的示例,仅适用于局部变量。由于上下文有限,编译器对这种情况进行了密切的处理。请注意0​​不为空,它是未定义的。

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

所以它是由设计。

0

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

0

在第一个样品小号是一个局部变量,编译器可以easialy检查使用数据之前小号 varible没有指定。

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

+0

s没有全球性的,它是一个实例-领域。 – 2009-09-11 21:02:46

3

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

  • 编译器不是100%正确的。如果通过反射修改实例,则“s”可能具有非空值。
  • 程序可以没有错误执行,如果该方法栏没有被调用
  • 这个程序可以是被触发用于测试的原因一个NullReferenceException的测试程序
相关问题