синтаксиса MSDN утверждает, что:разница между сбором Initializer
С помощью коллекции инициализатору вы не должны указывать несколько вызовов метода 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, значение2"
collection2 [ключ] = "значение2"
Я понимаю, что есть связь между старым синтаксисом и интерфейсом IEnumerable
и как компилятор находит метод Add
по именованию и т. д. Я также понимаю преимущества любого типа индексатора, подверженного новому синтаксису, как обсуждалось ранее в this SO answer.
Возможно, это все ожидаемые функции, с вашей точки зрения, но последствия мне не пригодились, и мне любопытно узнать больше.
Итак, интересно, есть ли источник документации в MSDN или в другом месте, который разъясняет эту разницу в поведении, которая поставляется с выбором синтаксиса. Я также задаюсь вопросом, знаете ли вы о других примерах, где этот выбор может иметь такое влияние, как при инициализации NameValueCollection
.
Документов вы ссылаетесь, чтобы сделать сказать, что это выше «новой» синтаксиса: * Можно указать индексированные элементы, если коллекция поддерживает индексацию. *. Для меня это означает, что он будет использовать индексатор для настройки. –
@CharlesMager Я как раз собирался опубликовать что-то подобное, увидев [это] (http://stackoverflow.com/questions/28076127/c6s-new-collection-initializer-clarification) – Rawling
@CharlesMager Это правда, что вы говорите, но я «вряд ли назову это« разъяснением », за исключением, возможно, для уже просвещенного;) Кроме того, вопрос - насколько различия в поведении идут - очевидно, применимы только к типам, которые подвержены« индексированию »и« добавлению », то, что также не обсуждается на этой странице. –