MSDN states that:
By using a collection initializer you do not have to specify multiple calls to the Add method of the class in your source code; the compiler adds the calls.
They also give this example, using the newer collection initialization syntax with brackets:
var numbers = new Dictionary<int, string> {
[7] = "seven",
[9] = "nine",
[13] = "thirteen"
};
However, when checking the IL code generated, it seems that this code does not at all result in any calls to the Add
method, but to rather to one set_item
, like so:
IL_0007: ldstr "seven"
IL_000c: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32, string>::set_Item(!0/*int32*/, !1/*string*/)
The "old" syntax with curly brackets in contrast gives the following:
// 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*/)
... As you can see, a call to Add
is the result, as expected. (One can only assume that the text on MSDN mentioned above is yet to be updated.)
I've so far discovered one case where this difference actually matters, and that is with the quirky System.Collections.Specialized.NameValueCollection
. This one allows for one key to point to more than one value. Initialization can be done in both ways:
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
};
... But because of the differences in how only the former actually calls the NameValueCollection::Add(string, string)
, the results differ when looking at the contents of each collection;
collection1[key] = "value1,value2"
collection2[key] = "value2"
I realize that there's a connection between the old syntax and the IEnumerable
interface, and how the compiler finds the Add
method by naming convention etcetera. I allso realize the benefits of any indexer type being subject to the new syntax, as discussed in this SO answer before.
Perhaps these are all expected features, from your point of view, but the implications had not occurred to me, and I'm curious to know more.
So, I wonder if there's a source of documentation at MSDN or elsewhere that clarifies this difference in behavior that comes with the choice of syntax. I also wonder if you know of any other examples where this choice may have such an impact as when initializing a NameValueCollection
.