19

我读过:

该团队通常忙于实现初始化器的其他变体。例如,您现在可以初始化 Dictionary 对象

但是看着:

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

对比

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

我看不出好处在哪里。它看起来一样。两者都只不过是一个名称-值集合。
他们用一对花括号换成一对方括号和一些逗号

问题:

使用新语法有什么附加价值?一个真实世界的例子将不胜感激。

4

4 回答 4

30

字典的主要优点是一致性。使用字典,初始化看起来与用法不同。

例如,您可以这样做:

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方法的类型。这恰好适用于 a Dictionary<TKey,TValue>,但这并不意味着它适用于任何基于索引的类型。

于 2015-01-21T20:37:42.077 回答
9

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

集合初始化器

  1. 实现IEnumerable接口。
  2. 定义一个可访问的Add()方法。(从 C#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或具有 add 方法,因此不能使用该语法。


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

能够在单个表达式中完全初始化对象通常很有用(在某些情况下,这是一种要求)。字典初始值设定项语法使执行此操作更容易,而无需使用集合初始值设定项的苛刻要求。

于 2015-01-21T20:37:05.267 回答
8

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

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

是允许的:这里的 key"a"有 value "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)
于 2016-02-28T18:54:49.040 回答
2

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

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

于 2015-01-24T09:53:35.043 回答