字典初始化器相比于集合初始化器有哪些好处?

51

最近有很多关于C# 6.0新特性的讨论。
其中最受关注的一个特性是在C# 6.0中使用Dictionary初始化程序。
但是请等一下,我们一直在使用集合初始化程序来初始化集合,并且可以在.NET 4.0和.NET 4.5中很好地初始化Dictionary(不知道旧版本如何)。例如:

Dictionary<int, string> myDict = new Dictionary<int, string>() {
    { 1,"Pankaj"},
    { 2,"Pankaj"},
    { 3,"Pankaj"}
};

那么C#6.0有什么新的变化?在C#6.0中他们所说的字典初始化程序是什么?


4
问题标题可以编辑为“集合初始化程序和字典初始化程序的区别是什么?”或“字典初始化程序相比于集合初始化程序有哪些优势?”,以区别于“可以通过简单的搜索得到答案的问题”。请注意,翻译保持了原意和语境,同时使句子通俗易懂。 - i3arnon
3个回答

77

虽然你可以使用集合初始化器来初始化一个字典,但这样做非常繁琐。特别是对于一个本应该是语法糖的东西。

字典初始化器要简洁得多:

var myDict = new Dictionary<int, string>
{
    [1] = "Pankaj",
    [2] = "Pankaj",
    [3] = "Pankaj"
};

更重要的是,这些初始化器不仅适用于字典,它们还可以用于支持索引器的任何对象,例如List<T>

var array = new[] { 1, 2, 3 };
var list = new List<int>(array) { [1] = 5 };
foreach (var item in list)
{
    Console.WriteLine(item);
}

输出:

1
5
3

16
不同之处在于旧版本调用的是Add方法(现在可能成为C#中的扩展方法),而新版本则调用索引器。对于字典来说,最终结果可能相同,但新版本可以用于具有索引器但没有Add方法的类型。 - Paulo Morgado
5
没错,当我看到问题和你的回答时,我觉得可能会被误解成是同一件事。我只是在加强你的回答。 - Paulo Morgado
1
@GuillermoRuffino 的索引是从零开始的。 - i3arnon
1
@PauloMorgado 还有调用索引器而不是 Add 的另一个重要副作用,这将导致 new Dictionary<int, string> { {1, "a"}, {1, "b"} }; 失败,但这将不会 new Dictionary<int, string> { [1] = "a", [1] = "b" };(并且 dict[1] 的值是 b,最新的赋值)。 - Teejay
1
@Teejay,这是最重要的区别。如果i3arnon能在他的回答中加入这一点,我会很感激。 - nawfal
显示剩余4条评论

3

强调最重要的区别,字典初始化程序调用索引器,因此在遇到重复键时执行更新,而集合初始化程序调用Add方法,会抛出异常。

总之,它们的不同之处可概括如下:

  1. Collection initializer calls Add method (for IEnumerables) where as dictionary initializer calls indexer. This has the Add vs Update semantic differences for dictionaries.

  2. Dictionary initializer is technically an object initializer, hence can be mixed with initializing other properties. For e.g.:

    new Dictionary<int, string>
    {
        [1] = "Pankaj",
        [2] = "Pankaj",
        [3] = "Pankaj",
        Capacity = 100,
    };
    

    but not

    new Dictionary<int, string>() 
    {
        { 1,"Pankaj" },
        { 2,"Pankaj" },
        { 3,"Pankaj" },
        Capacity = 100, // wont compile
    };
    
  3. Being just an object initializer, indexed initializer can be used for any class with an indexer, whereas collection initializer can be used only for IEnumerables, which should be obvious anyway.

  4. Collection initializer can be enhanced with custom Add extension methods, whereas ditionary initializer can't be (no extension indexer in C# yet).

  5. Dictionary initializer maybe subjectively slightly more readable when it comes to initializing a dictionary :)

  6. Dictionary initializer is C# 6.0 feature whereas collection initializer is available from C# 3.0 onwards.


0

使用这种方式,New 正在创建一个字典

Dictionary<int, string> myDict = new Dictionary<int, string>() {
    [1] = "Pankaj",
    [2] = "Pankaj",
    [3] = "Pankaj"
};

使用<index> = <value>的方式

已过时:字符串索引成员语法(如评论中所述)

Dictionary<int, string> myDict = new Dictionary<int, string>() {
        $1 = "Pankaj",
        $2 = "Pankaj",
        $3 = "Pankaj"
    };

摘自C# 6.0语言预览

要理解$运算符,请看AreEqual函数调用。注意在builtInDataTypes变量上调用“$Boolean”的Dictionary成员调用,即使Dictionary上没有“Boolean”成员也是如此。因为不需要显式成员,$运算符会调用字典的索引成员,相当于调用buildInDataTypes["Boolean"]。


10
据我所知,$ 运算符已经不存在了。 - i3arnon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接