【问题标题】:Can I use a collection initializer for Dictionary<TKey, TValue> entries?我可以为 Dictionary<TKey, TValue> 条目使用集合初始化程序吗?
【发布时间】: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"
   ...

但是正确的语法是什么?

【问题讨论】:

标签: c# .net generics collections c#-3.0


【解决方案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... -- stackoverflow.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 中的工作方式 - stackoverflow.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 个答案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-21
        • 1970-01-01
        • 1970-01-01
        • 2016-06-14
        • 1970-01-01
        • 2011-06-15
        • 1970-01-01
        相关资源
        最近更新 更多