2013-03-20 33 views
3

我碰上運行下面的代碼NullReferenceException例外:接口集合成員的奇怪行爲

public class Container 
{ 
    public IList<string> Items { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var container = new Container() { Items = {"Test"} }; 
    } 
} 

這是合乎邏輯的compiller無法創建interaface實例,但我得到了一個運行時異常,而不是編譯時。當我進一步調查此行爲時,我更加困惑:

var container = new Container() { Items = {} }; //Legal, Items is null after initialization 

    var container = new Container() { Items = { "Test" } }; //Legal, throws exception 
    container.Items = {}; //Illegal doesn't compile 
    container.Items = {"Test"}; //Illegal doesn't compile 

這是某種錯誤還是我不明白? 而我使用.NET Framework 4.0

回答

3

它編譯,因爲編譯器沒有關於知識是List已經在其他地方初始化了。你可以把它加入初始化成一個構造工作:

public class Container 
{ 
    public IList<string> Items { get; set; } 

    public Container() 
    { 
     Items = new List<string>(); 
    } 
} 

或改變屬性爲隱藏字段,它是在創建類的實例時初始化:

private IList<string> items = new List<string>(); 
public IList<string> Items 
{ 
    get { return items; } 
    set { items = value; } 
} 

然後,var container = new Container() { Items = { "Test" } };作品就好了。

在運行時.Add()方法爲集合初始值設定項組中的每個項目調用。當屬性未使用new List<string>進行初始化時,它具有null值,這就是爲什麼NullReferenceException被引發。

Object and Collection Initializers (C# Programming Guide)

通過使用集合初始化你不必指定多個 調用在源代碼之類的Add方法; 編譯器 添加了調用

+0

我一直認爲'var container = new Container(){Items = {「Test」}}'創建集合並添加項目到集合中,我錯了:( – Andrew 2013-03-20 10:31:44

0

你沒有初始化List

var container = new Container() { Items = new List<string>() { "Test" } }; 

通過下面的是合法的,因爲編譯器的方式有什麼不妥(語法是正確的,等)

var container = new Container() { Items = {} }; 

但由於編譯器不知道Items名單尚未初始化(你不傳遞任何物品集合中initializator {})的.Add方法將不會被調用的List和運行時間不會知道Items對象爲空

在另一方面下面是合法的編譯器,但它在運行時拋出一個異常,因爲你嘗試初始化傳遞一個項目的列表(由於上面解釋的原因,編譯器是正確的),所以當運行時將調用場景後面的.Add方法時,它會拋出空引用異常,因爲Items尚未初始化

var container = new Container() { Items = { "Test" } }; 
+1

我認爲這個問題是爲什麼第一行 - '新的Container(){Items = {}};'正在編譯 – Habib 2013-03-20 09:56:11

+0

新列表很容易。主要問題是爲什麼它甚至是編譯。 – Andrew 2013-03-20 10:00:19

+0

我編輯了我的答案 – 2013-03-20 10:15:23