web-dev-qa-db-ja.com

C#でさまざまな型を保持する辞書を作成するにはどうすればよいですか

値が異なるタイプになる可能性があるキー/値のペアを保存する何らかの方法が必要です。

だから私はやりたい:

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

このようなストレージはどのように見えるべきですか?ありがとう、エリック

41
Enrico

C#4/.NET 4ではDictionary<string, dynamic>を使用できますが、それ以外は、intstring、および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
65
Jon Skeet

couldタイプ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;

等.

23
Steve Haigh

使用しない理由:

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

厳密に型指定されたデータコレクションが必要ない場合、HashTableがあなたの状況に適していると思います。辞書の実装用に提案された別のポスターのように、このための拡張メソッドを作成することもできます。

例えば。

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
John Pappin
Dictionary<string, object>
2

昔の質問かもしれませんが、答えを見つけるためにここに来る人たちに話しかけています

値が固定タイプでない場合、選択肢の1つがHashtableを使用している場合、Dictionaryと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では、たとえばHashtableのaddメソッドからわかるように、両方とも本質的にオブジェクトとみなされるため、キーと値の両方に型はありません:

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

キーや値が固定されていない場合は、Hashtableを使用することをお勧めします。したがって、追加の拡張メソッドを追加したり、デフォルトの動作をオーバーライドしたりする必要はまったくありません。

Dictionary<string,object>を使用してから、必要なものを挿入できます。ただし、結果を取得するときは、正しい型に結果をキャストする必要があります。

あなたの例を見ると、データを保存するための単純なクラスがあなたが望むものよりも多く、より良い型安全を可能にするかどうかを検討したいかもしれません。クラスに入れるものが限られているかどうか、または辞書の潜在的に無制限/不明なストレージが必要かどうかによって異なります。

1
Chris

辞書が明らかに最も速いソリューションです。

別の方法は、実際の値とその型に関する情報を保存できるカスタムクラスを保存することです。

0
il_guru