C#6的新集合初始化程序 - 澄清?

时间:2015-01-21 20:21:20

标签: c# dictionary c#-6.0 collection-initializer

我读过:

  

团队一直忙于实施其他变体   初始化。例如,您现在可以初始化Dictionary对象

但是看着:

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

VS

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

我看不出有什么好处。它看起来一样。两者都只是一个名值集合 他们用成对的方括号和一些逗号交换成对的花括号

问题:

使用新语法的附加值是什么?一个现实世界的例子将非常感激。

4 个答案:

答案 0 :(得分:23)

字典的主要优点是一致性。使用字典时,初始化与使用情况看起来不一样。

例如,你可以这样做:

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

但是使用初始化语法,你必须使用大括号:

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

新的C#6索引初始化语法使初始化语法与索引使用更加一致:

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

但是,更大的优势是此语法还提供了允许您初始化其他类型的好处。具有索引器的任何类型都将允许通过此语法进行初始化,其中旧集合初始值设定项仅适用于实现IEnumerable<T>并具有Add方法的类型。这恰好适用于Dictionary<TKey,TValue>,但这并不意味着它适用于任何基于索引的类型。

答案 1 :(得分:9)

第一种情况中的代码使用集合初始化程序语法。为了能够使用集合初始化程序语法,类必须:

Collection Initializers

  1. 实施IEnumerable界面。
  2. 定义可访问的Add()方法。 (从C#6 / VS2015开始,它可能是一种扩展方法)
  3. 所以这样定义的类可以使用语法:

    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或具有add方法,因此无法使用该语法。


    另一方面,许多对象定义(可设置)索引器。这是使用dicionary初始化程序的地方。拥有索引器可能是有意义的,但不一定是IEnumerable。使用字典初始化程序,您不需要IEnumerable,您不需要Add()方法,您只需要一个索引器。

    能够在单个表达式中完全初始化对象通常很有用(在某些情况下,需要)。字典初始化器语法使得在没有使用集合初始化器的苛刻要求的情况下更容易实现。

答案 2 :(得分:5)

这可能是一个值得怀疑的功能,但新语法允许您多次设置相同的功能。

        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)

答案 3 :(得分:3)

本身没有技术优势;它只是语法糖(就像许多新的C#6功能一样)。事实上C# feature descriptions PDF只提到了一个优雅的问题:

  

对象和集合初始值设定项对于声明性地初始化对象的字段和属性或为集合提供一组初始元素非常有用。使用索引器初始化字典和其他对象不太优雅。我们正在为对象初始化器添加一个新语法,允许您通过新对象具有的任何索引器将值设置为