С# 6 новый Инициализатор коллекции - Уточнение?

Я читал, что:

Команда, как правило, была занята реализацией других вариантов Инициализаторы. Например, теперь вы можете инициализировать объект Dictionary

Но глядя на:

var Dic = new Dictionary<string,int>{ {"x",3}, {"y",7} };

VS

var Dic = new Dictionary<string,int>{ ["x"]=3, ["y"]=7 };

Я не вижу, где это преимущество. это выглядит так же. Оба являются не чем иным, как коллекцией имен. Они поменяли пары фигурных скобок для пар квадратных скобок и некоторых запятых

Вопрос:

Какова добавленная стоимость использования нового синтаксиса? пример с реальным миром был бы очень оценен.

Ответ 1

Основным преимуществом здесь со словарем является согласованность. С помощью словаря инициализация выглядела не так, как использование.

Например, вы можете сделать:

var dict = new Dictionary<int,string>();
dict[3] = "foo";
dict[42] = "bar";

Но используя синтаксис инициализации, вам нужно было использовать фигурные скобки:

var dict = new Dictionary<int,string>
{
    {3, "foo"},
    {42, "bar"}
};

Новый синтаксис инициализации индекса С# 6 делает синтаксис инициализации более согласованным с использованием индекса:

var dict = new Dictionary<int,string>
{ 
    [3] = "foo",
    [42] = "bar"
};

Однако большее преимущество заключается в том, что этот синтаксис также дает возможность инициализировать другие типы. Любой тип с индексом позволяет инициализировать этот синтаксис, когда старые инициализаторы коллекции работают только с типами, которые реализуют IEnumerable<T> и имеют метод Add. Это случилось с Dictionary<TKey,TValue>, но это не значит, что он работал с любым типом, основанным на индексе.

Ответ 2

Код в первом случае использует синтаксис инициализатора коллекции. Чтобы иметь возможность использовать синтаксис инициализатора коллекции, класс должен:

Инициализаторы коллекции:

  • Внедрить интерфейс IEnumerable.
  • Определите доступный метод Add(). (с С# 6/VS2015, это может быть метод расширения)

Таким образом, класс, определенный таким образом, может использовать синтаксис:

public class CollectionInitializable : IEnumerable
{
    public void Add(int value) { ... }
    public void Add(string key, int value) { ... }
    public IEnumerator GetEnumerator() { ... }
}

var obj = new CollectionInitializable
{
    1,
    { "two", 3 },
};

Не все объекты IEnumerable или имеют метод добавления и поэтому не могут использовать этот синтаксис.


С другой стороны, многие объекты определяют (устанавливаемые) индексы. Здесь используется инициализатор dicionary. Возможно, имеет смысл иметь индексаторы, но необязательно быть IEnumerable. С помощью инициализатора слова вам не нужно быть IEnumerable, вам не нужен метод Add(), вам нужен только индекс.

Возможность полностью инициализировать объект в одном выражении обычно полезна (и в некоторых контекстах - требование). Синтаксис инициализатора словаря упрощает выполнение этого без крутых требований использования инициализаторов коллекции.

Ответ 3

Это может быть сомнительная функция, но новый синтаксис позволяет вам устанавливать одинаковые несколько раз.

        private static Dictionary<string, string> test1
        = new Dictionary<string, string>() {
            ["a"] = "b",
            ["a"] = "c"
        };

разрешено: здесь ключ "a" имеет значение "c".

В отличие от этого, используя

private static Dictionary<string, string> test2
    = new Dictionary<string, string>() {
        { "a","b" },
        { "a","c" },
    };

создает исключение:

Unbehandelte Ausnahme: System.TypeInitializationException: Der Typeninitialisierer für "ConsoleApplication1.Program" hat eine Ausnahme verursacht. 
---> System.ArgumentException: Ein Element mit dem gleichen Schlüssel wurde bereits hinzugefügt.
   bei System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   bei System.Collections.Generic.Dictionary``2.Insert(TKey key, TValue value, Boolean add)
   bei System.Collections.Generic.Dictionary``2.Add(TKey key, TValue value)
   bei ConsoleApplication1.Program..cctor() in Program.cs:Zeile 19.
   --- Ende der internen Ausnahmestapelüberwachung ---
   bei ConsoleApplication1.Program.Main(String[] args)

Ответ 4

Там нет технической выгоды как таковой; это просто синтаксический сахар (как и многие новые функции С# 6). описания функций С# PDF, на самом деле, упоминает только вопрос элегантности:

Инициализаторы объектов и коллекций полезны для декларативно инициализации полей и свойств объектов или предоставления коллекции исходного набора элементов. Инициализация словарей и других объектов с помощью индексаторов менее изящна. Мы добавляем новый синтаксис к инициализаторам объектов, которые позволяют вам устанавливать значения для ключей через любого индексатора, что новый объект имеет