【问题标题】:How do I create a Dictionary that holds different types in C#如何在 C# 中创建包含不同类型的字典
【发布时间】:2011-05-05 13:22:29
【问题描述】:

我需要某种方式来存储键/值对,其中值可以是不同的类型。

所以我喜欢这样做:

 int i = 12;
 string s = "test";
 double x = 24.1;

 Storage.Add("age", i);
 Storage.Add("name", s);
 Storage.Add("bmi", x);

稍后检索值:

 int a = Storage.Get("age");
 string b = Storage.Get("name");
 double c = Storage.Get("bmi");

这样的存储应该是什么样子? 谢谢, 埃里克

【问题讨论】:

    标签: c# dictionary hashtable


    【解决方案1】:

    也许这是一个老问题,但我是在向来这里寻找答案的人发问

    如果值不是固定类型,其中一种选择是使用 Hashtable 请看 D​​ictionary 和 Hashtable 的实现

        public class Dictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, ICollection, IDictionary, IDeserializationCallback, ISerializable
         {
                  ... 
         }

    public class Hashtable : ICollection, IEnumerable, IDictionary, ISerializable, IDeserializationCallback, ICloneable
      {
       ...
      }

    从上面的代码 sn-ps 中可以更清楚地看到,两者都实现了字面上相同的接口,但在 Hashtable 中,键和值都没有类型,因为它们都被认为是本质上的对象,例如你可以从 add Hashtable中的方法:

    public virtual void Add(object key, object value);

    因此,对于没有固定键和/或值的情况,我建议使用 Hashtable,因此您无需再添加额外的扩展方法或覆盖字典的默认行为。

    【讨论】:

      【解决方案2】:

      鉴于您不想要强类型的数据收集,那么我认为HashTable 会适合您的情况。您也可以为此创建一个扩展方法,就像为 Dictionary 实现建议的另一张海报一样。

      例如

      public static class StorageExtentions
      {
          public static T Get<T>(this Hashtable table, object key)
          {
              return (T) table[key];
          }
      }
      

      您的代码将如下所示:

      int i = 12;
      string s = "test";
      double x = 24.1;
      Hashtable Storage = new Hashtable();
      Storage.Add("age", i);
      Storage.Add("name", s);
      Storage.Add("bmi", x);
      int a = Storage.Get<int>("age");
      string b = Storage.Get<string>("name");
      double c = Storage.Get<double>("bmi");
      

      【讨论】:

        【解决方案3】:

        可以声明一个只包含object 类型的字典,然后转换您的结果; .例如

        Dictionary<string, object> storage = new Dictionary<string,object>();
        
        storage.Add("age", 12);
        storage.Add("name", "test");
        storage.Add("bmi", 24.1);
        
        int a = (int)storage["age"];
        string b = (string)storage["name"];
        double c = (double)storage["bmi"];
        

        但是,这并不是那么优雅。如果你知道你总是要存储年龄、姓名、bmi,我会创建一个对象来封装这些并存储它们。例如

        public class PersonInfo
        {
            public int Age { get; set; }
            public string Name { get; set; }
            public double Bmi { get; set; }
        }
        

        然后使用字典中的那个...例如

        PersonInfo person1 = new PersonInfo { Name = "test", Age = 32, Bmi = 25.01 };
        
        int age = person1.Age;
        

        等等

        【讨论】:

          【解决方案4】:

          为什么不使用:

          Dictionary<string, object>
          

          您可以创建一个扩展方法来在获取它们时进行转换:

          public static class DictionaryExcetions
          {
              public static T Get<T>(this Dictionary<string, object> instance, string name)
              {
                  return (T)instance[name];
              }
          
          }
          
          var age = dictionary.Get<int>("age");
          

          【讨论】:

            【解决方案5】:

            字典显然是最快的解决方案。

            另一种方法是存储一个自定义类,您可以在其中存储实际值和有关其类型的信息

            【讨论】:

              【解决方案6】:

              您可以使用Dictionary&lt;string,object&gt;,然后您可以将任何您想要的内容放入其中。但是,当您将结果输出时,您必须将它们转换为正确的类型。

              查看您的示例,您可能想考虑存储数据的简单类是否更符合您的要求并允许更好的类型安全性。这取决于您是否在课堂上放了有限的东西,或者您是否确实需要字典的潜在无限/未知存储。

              【讨论】:

                【解决方案7】:
                Dictionary<string, object>
                

                【讨论】:

                  【解决方案8】:

                  好吧,您可以在 C# 4 / .NET 4 中使用 Dictionary&lt;string, dynamic&gt; - 但除此之外,您不能完全按照显示的代码执行此操作,因为没有可隐式转换为 int、@987654323 的类型@ 和 double。 (您可以编写自己的,但必须分别列出每种类型。)

                  您可以使用Dictionary&lt;string, object&gt;,但您需要转换结果:

                  int a = (int) Storage.Get("age");
                  string b = (string) Storage.Get("name");
                  double c = (double) Storage.Get("bmi");
                  

                  或者,您可以将Get 方法设为通用:

                  int a = Storage.Get<int>("age");
                  // etc
                  

                  【讨论】:

                  • 也许有人应该创建一个 Variant 类型?救命,我瞎了!
                  • 我同意 Jon Skeet 的观点。再次。但是做这样的事情意味着你做错了什么。您应该首先考虑为什么需要在单个字典中存储不同值的原因。
                  • 非常感谢,通用的 Get 方法正是我要找的东西!!
                  • @MinhTran:当然,除非您需要存储各种值。如果您可以使事情成为类型安全的,那就太好了,但在很多情况下您确实不能。
                  • @BH 您需要在Dictionary 上创建通用扩展。它不是 .NET 的一部分,所以你并不疯狂
                  猜你喜欢
                  • 2020-12-06
                  • 2011-03-06
                  • 2020-03-01
                  • 2017-10-08
                  • 2011-06-09
                  • 2013-07-13
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-09-09
                  相关资源
                  最近更新 更多