Как создать словарь, который содержит различные типы в C # - PullRequest
40 голосов
/ 05 ноября 2010

Мне нужен какой-то способ хранения пар ключ / значение, где значение может быть разных типов.

Поэтому мне нравится делать:

 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");

Как должно выглядеть хранилище, подобное этому?Спасибо, Эрик

Ответы [ 8 ]

65 голосов
/ 05 ноября 2010

Ну, вы могли бы использовать Dictionary<string, dynamic> в C # 4 / .NET 4 - но кроме этого вы не можете сделать это с точно показанным кодом, потому что нет типа, который неявно преобразуется в int, string и double.(Вы можете написать свой собственный, но вам придется перечислять каждый тип отдельно.)

Вы можете использовать Dictionary<string, object>, но тогда вам нужно будет привести результаты:

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
23 голосов
/ 05 ноября 2010

Вы можете объявить словарь, содержащий только тип object, а затем привести результаты; .e.g.

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;

и т.д.

7 голосов
/ 05 ноября 2010

Почему бы не использовать:

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");
2 голосов
/ 05 ноября 2010

Учитывая, что вам не нужен сбор строго типизированных данных, я бы подумал, что HashTable подойдет для вашей ситуации. Для этого вы также можете создать метод Extention, например, другой плакат, предложенный для реализации 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");
2 голосов
/ 05 ноября 2010
Dictionary<string, object>
1 голос
/ 12 августа 2018

возможно, это старый вопрос, но я обращаюсь к парням, которые приходят сюда, чтобы найти ответ

если значение не является фиксированным типом, один из вариантов использует Hashtable пожалуйста, посмотрите на реализацию словаря и 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
  {
   ...
  }

так как это становится более понятным из приведенных выше фрагментов кода, оба реализуют буквально одни и те же интерфейсы, но в Hashtable нет типа и для ключа, и для значения, поскольку оба они считаются внутренними объектами, как, например, вы можете видеть из метода add Hashtable:

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

поэтому для случаев с нефиксированными ключами и / или значениями я рекомендую использовать Hashtable, поэтому вам не нужно добавлять дополнительные методы расширения или переопределять поведение по умолчанию.

1 голос
/ 05 ноября 2010

Вы можете использовать Dictionary<string,object>, а затем можете положить в него все, что захотите.Однако вам придется приводить результаты к нужному типу, когда вы получаете их.

Глядя на свой пример, вы можете подумать, может ли простой класс для хранения данных быть больше, чем вы хотите, и разрешитьлучший тип безопасности.Это зависит от того, есть ли у вас в классе ограниченный набор вещей или вам нужно потенциально неограниченное / неизвестное хранилище словаря.

0 голосов
/ 05 ноября 2010

Словарь, безусловно, самое быстрое решение.

Другим способом может быть сохранение пользовательского класса, в котором вы можете хранить фактическое значение и информацию о его типе

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...