我可以为 Dictionary<TKey, TValue> 条目使用集合初始化程序吗?

Posted

技术标签:

【中文标题】我可以为 Dictionary<TKey, TValue> 条目使用集合初始化程序吗?【英文标题】:Can I use a collection initializer for Dictionary<TKey, TValue> entries? 【发布时间】:2010-10-04 10:45:02 【问题描述】:

我想为下一段代码使用集合初始化器:

public Dictionary<int, string> GetNames()

    Dictionary<int, string> names = new Dictionary<int, string>();
    names.Add(1, "Adam");
    names.Add(2, "Bart");
    names.Add(3, "Charlie");
    return names;

所以通常应该是这样的:

return new Dictionary<int, string>
 
   1, "Adam",
   2, "Bart"
   ...

但是正确的语法是什么?

【问题讨论】:

查看这篇文章:marcin-chwedczuk.github.io/… Proper way to initialize a C# dictionary with values already in it?的可能重复 不要认为这是骗人的,因为他们问的不是速记字典声明语法,而是为什么速记在他们的(古代)设置中不起作用。 【参考方案1】:
return new Dictionary<int, string>
 
    1, "Adam" ,
    2, "Bart" ,
   ...

【讨论】:

【参考方案2】:

语法略有不同:

Dictionary<int, string> names = new Dictionary<int, string>()

     1, "Adam" ,
     2, "Bart" 

请注意,您实际上是在添加值的元组。

作为旁注:集合初始化器包含的参数基本上是任何 Add() 函数的参数,这些函数在编译时参数类型方面派上用场。也就是说,如果我有一个集合:

class FooCollection : IEnumerable

    public void Add(int i) ...

    public void Add(string s) ...

    public void Add(double d) ...

以下代码完全合法:

var foos = new FooCollection()  1, 2, 3.14, "Hello, world!" ;

【讨论】:

很好的答案,我不知道!无论如何,字典初始化程序什么时候工作?它仅适用于 Dictionary 子类还是也适用于 ICollection>? @Shimmy Collection 初始化器适用于任何实现IEnumerable 并且 具有Add() 方法的东西。 @Shimmy:字典是集合 @JohnSaunders 但是字典初始化程序接受Add 的两个参数。 @Shimmy:这有什么关系?关键是它可以与实现IEnumerable&lt;T&gt; 并具有Add 方法的any 类一起使用。如果 Add 方法采用 3 参数,那么括号中需要 3 个对象。【参考方案3】:
var names = new Dictionary<int, string> 
   1, "Adam" ,
   2, "Bart" ,
   3, "Charlie" 
;

【讨论】:

初始化程序什么时候工作?它仅适用于Dictionary&lt;TKey, TValue&gt; 子类还是也适用于ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt; 在C# 3.0之后可以使用var代替声明类型,或者如果离开声明类型可以省略new Dictio... -- ***.com/questions/5678216/… @drzaus:虽然使用 var 是一种丑陋、丑陋的做法; C# 是一种强类型语言。 @Nyerguds:什么? var 字面上只是节省了您的击键次数,它是 implicitly strongly typed。 @Nyerguds -- 我猜你有权发表你的意见,但如果你立即初始化你的变量,那么使用var 和重复使用SomeType obj = new SomeType... 之间几乎没有区别。而且由于您不能在不立即初始化的情况下声明var obj;,所以我只是看不到问题所在。真的,我正在努力学习,但我无法理解你的立场。【参考方案4】:

如果您正在寻找稍微不那么冗长的语法,您可以像这样创建Dictionary&lt;string, object&gt;(或任何您的类型)的子类:

public class DebugKeyValueDict : Dictionary<string, object>



然后就这样初始化

var debugValues = new DebugKeyValueDict
                  
                        "Billing Address", billingAddress , 
                        "CC Last 4", card.GetLast4Digits() ,
                        "Response.Success", updateResponse.Success 
                  );

相当于

var debugValues = new Dictionary<string, object>
                  
                        "Billing Address", billingAddress , 
                        "CC Last 4", card.GetLast4Digits() ,
                        "Response.Success", updateResponse.Success 
                  );

好处是你可以获得所有你可能想要的编译类型的东西,比如能够说

is DebugKeyValueDict 而不是is IDictionary&lt;string, object&gt;

或在以后更改键或值的类型。 如果你在一个 razor cshtml 页面中做这样的事情,看起来会更好看。

除了不那么冗长,你当然可以为这个类添加额外的方法来满足你的需要。

【讨论】:

这基本上是 ViewDataDictionary 在 MVC 中的工作方式 - ***.com/questions/607985/… 我尝试将类型作为字典和类型化数组的“别名”,假设在类型化世界中使用预定义类型会更安全。结果发现它并没有那么有用泛型和 linq。【参考方案5】:

在以下代码示例中,Dictionary&lt;TKey, TValue&gt; 使用 StudentName 类型的实例进行初始化。

  Dictionary<int, StudentName> students = new Dictionary<int, StudentName>()
  
       111, new StudentName FirstName="Sachin", LastName="Karnik", ID=211,
       112, new StudentName FirstName="Dina", LastName="Salimzianova", ID=317,
       113, new StudentName FirstName="Andy", LastName="Ruth", ID=198
  ;

来自msdn

【讨论】:

【参考方案6】:

这个问题被标记为c#-3.0,但为了完整起见,我会提到 C# 6 中可用的新语法,以防您使用 Visual Studio 2015(或 Mono 4.0):

var dictionary = new Dictionary<int, string>

   [1] = "Adam",
   [2] = "Bart",
   [3] = "Charlie"
;

注意:如果您更喜欢,其他答案中提到的旧语法仍然有效。同样,为了完整起见,这里是旧语法:

var dictionary = new Dictionary<int, string>

    1, "Adam" ,
    2, "Bart" ,
    3, "Charlie" 
;

需要注意的另一件很酷的事情是,无论使用哪种语法,您都可以根据需要保留最后一个逗号,这样可以更轻松地复制/粘贴其他行。例如,下面的编译就好了:

var dictionary = new Dictionary<int, string>

   [1] = "Adam",
   [2] = "Bart",
   [3] = "Charlie",
;

【讨论】:

【参考方案7】:

是的,我们可以在字典中使用集合初始化器。如果我们有这样的字典-

Dictionary<int,string> dict = new Dictionary<int,string>();  
            dict.Add(1,"Mohan");  
            dict.Add(2, "Kishor");  
            dict.Add(3, "Pankaj");  
            dict.Add(4, "Jeetu");

我们可以如下初始化它。

Dictionary<int,string> dict = new Dictionary<int,string>  
              

                1,"Mohan" ,  
                2,"Kishor" ,  
                3,"Pankaj" ,  
                4,"Jeetu"   

            ; 

【讨论】:

已经有 6 个其他答案展示了如何做到这一点。我们不需要显示相同内容的第 7 个答案。

以上是关于我可以为 Dictionary<TKey, TValue> 条目使用集合初始化程序吗?的主要内容,如果未能解决你的问题,请参考以下文章

Dictionary<TKey, TValue> 的线程安全

ConcurrentDictionary与Dictionary

System.Collections.Generic.Dictionary<TKey,TValue>

Dictionary<TKey, TValue> 中的散列过程是如何工作的

为啥 Dictionary<TKey, TValue> 上的这个 Linq 查询不能作为数据源工作

Lookup<TKey, TElement> 的意义何在?