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的測試程序
相關問題