通過使用集合初始化你沒有指定要在源代碼之類的Add方法多次調用;編譯器添加這些調用。
他們還舉這個例子,使用帶有括號中的較新的集合初始化語法:
var numbers = new Dictionary<int, string> {
[7] = "seven",
[9] = "nine",
[13] = "thirteen"
};
然而,檢查產生的IL代碼時,似乎這個代碼根本不會產生任何通話到Add
方法,而是寧可一個set_item
,像這樣:
IL_0007: ldstr "seven"
IL_000c: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32, string>::set_Item(!0/*int32*/, !1/*string*/)
「老」的語法與此相反大括號給出如下:
// C# code:
var numbers2 = new Dictionary<Int32, String>
{
{7, "seven"},
{9, "nine"},
{13, "thirteen"}
};
// IL code snippet:
// ----------
// IL_0033: ldstr "seven"
// IL_0038: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32, string>::Add(!0/*int32*/, !1/*string*/)
...正如您所看到的,正如預期的那樣,調用Add
是結果。 (人們只能假定上面提到的MSDN上的文本還沒有更新。)
我到目前爲止發現了這種差異實際上很重要的一種情況,那就是與古怪的System.Collections.Specialized.NameValueCollection
。這一個允許一個鍵指向多個值。初始化可以以兩種方式來完成:
const String key = "sameKey";
const String value1 = "value1";
const String value2 = "value2";
var collection1 = new NameValueCollection
{
{key, value1},
{key, value2}
};
var collection2 = new NameValueCollection
{
[key] = value1,
[key] = value2
};
前怎麼只有實際調用NameValueCollection::Add(string, string)
,看着每一個集合的內容時,結果不同的差異......但因爲;
collection1 [鍵] = 「值1,值」
collection2 [鍵] = 「VALUE2」
我知道有舊的語法和IEnumerable
接口之間的連接,和編譯器如何通過命名約定等找到Add
方法。我也意識到任何索引器類型受益於新語法的好處,如之前的this SO answer中所討論的。
從您的角度來看,也許這些都是預期的功能,但這些影響並沒有發生在我身上,我很想知道更多。
所以,我想知道是否有MSDN或其他地方的文檔來源闡明瞭語法選擇帶來的行爲差異。我還想知道,如果您知道其他任何示例,這些選擇可能會對初始化NameValueCollection
產生如此影響。
您參考不說,這上面的「新」語法文檔:*你可以,如果集合支持索引指定索引元素。 *。對我而言,這意味着它將使用索引器來進行設置。 –
@CharlesMager我正要發佈類似看到[這個]後(http://stackoverflow.com/questions/28076127/c6s-new-collection-initializer-澄清) – Rawling
@CharlesMager這是真的你說什麼,但我我們幾乎不會說這是一個「澄清」,也許除了已經開明的一個;)而且,這個問題 - 就行爲差異而言 - 顯然只適用於同時受到「索引」和「增加」的類型,這個頁面上也沒有討論過。 –