2015-12-21 119 views
5

假設,我們有一個非常簡單的類:集合初始化的怪異語法

class ObjectList { 
    public List<string> List1 { get; } = new List<string>(); 
    public List<string> List2 { get; set; } 
} 

,我們想使這個類的一個實例:

ObjectList objectList = new ObjectList { 
    List1 = { "asdf", "qwer" }, 
    List2 = new List<string> { "zxcv", "1234" } 
}; 

所以,在列表2的情況下,好吧,使用「=」我們設置屬性。但是,在List1的情況下,它看起來像我們設置屬性,但實際上,我們假設在之前的某個位置設置它,並且在這裏我們只設置值。它和數組初始化非常相似:

string[] arr = { "val1", "val2" } 

爲什麼C#在這裏使用這種混淆語法?

編輯: 我想我很困惑與C#6.0語法的觀衆,但它不是重點。讓我們使用舊的C#3.0和.net 2.0。並允許增添更多的樂趣也該增加一些值(「1」和「2」)的列表,從開始,傑夫梅爾卡多推薦:

class Program { 
    static void Main(string[] args) { 
     ObjectList objectList = new ObjectList { 
      List1 = { "asdf", "qwer" }, 
     }; 
    } 
} 
class ObjectList { 
    List<string> _List1 = new List<string>() { "1", "2" }; 
    public List<string> List1 { 
     get { 
      return _List1; 
     } 
    } 
} 

它顯示了同樣怪異的語法。最後,我列出了名單{「1」,「2」,「asdf」,「qwer」},這更加令人困惑。我可以期待這一點。

+1

編譯? List1沒有公共setter,所以你不應該在initializer語法中設置它。 –

+1

它的確如此。編譯器實際上將該語法轉換爲調用'.Add()' –

+0

我同意,這種語法真的很奇怪。在語義上,它更像'+ ='。嵌套對象初始化器完全一樣 - 沒有構造函數調用,初始化器只設置屬性。 –

回答

2

答案已經his answer to Why is an Add method required for { } initialization?被賦予通過Eric Lippert

的通過設計通過集合初始化典型使用場景激勵的目標是使可能存在的集合類型的初始化表達式中的語法,使集合初始化可能嵌入在查詢理解中或轉換爲表達式樹。

每隔一個場景的優先級較低; 該功能完全存在,因爲它有助於使LINQ工作

因此,即使在創建只讀集合時該語法更有意義,它仍然被添加,因此它們可以按時交付LINQ。

+0

嗯..有趣的故事。但在LINQ中它有什麼用處? –

+0

它在引用中說明了它的正確性:「在表達式語法中可以對現有集合類型進行初始化」 –

+0

您可以提供一個示例嗎?我想我從來沒有這樣用過,所以我有麻煩想象它。 –

3

爲什麼C#在這裏使用這種混亂的語法?

你是對的,這有點奇怪,但那是因爲你混合了2個原則。正如幾個意見已經指出的那樣,當=左邊的項目是集合時,{ item1, items2 }語法被轉換爲.Add(itemN)調用

所以怪事是那

List<SomeClass> list = new List<SomeClass> { item1, item2 }; 
SomeClass[] array = { item1, item2 }; 

區別對待事實的結果。

另一部分是你的樣本移動new List<SomeClass>左右,但它在兩種情況下。

+1

我寧願說奇怪是賦值運算符('=')沒有做任何賦值的結果。 –

+0

我還沒有完整的圖片。 C#,所有語言。看起來非常整齊,但分配.add()看起來像是一種語言中的錯誤。 C#團隊必須有一個非常嚴肅的理由來添加這個,我想知道它。 –