2016-08-10 21 views
1

使用對象初始值設定項時,我嘗試通過數組初始值設定項錯誤地實例化ICollection(我忘記了new ...部分)。奇怪的是,編譯器沒有在編譯時抱怨,而是在運行時得到了NullReferenceException。數組初始化器在編譯時有效,但在運行時在對象初始化器內運行時失敗

下面是一些代碼,總結情況:

public class FakeClass 
{ 
    public ICollection<string> StringsCollection { get; set; } 

    public string[] StringsArray { get; set; } 
} 

FakeClass c = new FakeClass(); 
c.StringsCollection = { "test" }; // doesn't compile - ok 
c.StringsCollection = new string[] { "test" }; // compiles - ok 
c.StringsArray = { "test" }; // doesn't compile - ok 
c.StringsArray = new string[] { "test" }; // compiles - ok 

string[] strings = { "sdfqgrt" }; // compiles - ok 
strings = { "sdfqgrt" }; // doesn't compile - ok 

FakeClass c2 = new FakeClass 
{ 
    StringsCollection = { "rthtj" }, // compiles and throws at run - why? 
    StringsArray = { "egryjt" } // doesn't compile - ok 
}; 

我當然明白爲什麼代碼不能運行,但我很好奇,編譯器如何能夠接受這樣的事情。

+0

您正在使用不會初始化ICollection的{get; set}。在類的構造函數中添加初始化或替換{get;設置;}調用構造函數:new ICollection () – jdweng

+0

初始化程序使用很好的語法糖,太多的糖往往會產生爛牙。語法是有效的,你使用的是* collection *初始值設定項(不是字段初始值設定項),它只需要一個Add()方法。所以它調用* getter *而不是setter來獲取集合引用,它是空的。避免這樣的錯誤並不容易,你必須參加硬敲門學校。 –

回答

2
StringsCollection = { "rthtj" } 

這段代碼沒有錯。它調用默認的Add方法並將該字符串添加到集合中。

NRE異常,因爲你的財產尚未初始化。

這將工作

public ICollection<string> StringsCollection { get; set; } = new List<string>(); 

更新對評論

回答這個代碼

FakeClass c = new FakeClass(); 
c.StringsCollection = new string[] { "test" }; 

FakeClass c2 = new FakeClass 
{ 
    StringsCollection = { "dd" } 
}; 

看就IL並注意不同的第一間和第二個StringCollection

IlSpy

對於你需要像new string[] {}或新表()爲您使用集合初始化的getter情況下表達setter情況。

+0

的確,我看到某處調用了一個Add方法。但爲什麼'c.StringsCollection = {「test」};'甚至沒有編譯呢? –

相關問題