web-dev-qa-db-fra.com

Comment créer un dictionnaire contenant différents types en C #

J'ai besoin d'une sorte de moyen de stocker des paires clé/valeur où la valeur peut être de différents types.

Donc j'aime faire:

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

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

Et récupérez plus tard les valeurs avec:

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

À quoi devrait ressembler un stockage comme celui-ci? Merci, Erik

41
Enrico

Eh bien, vous pouvez utiliser Dictionary<string, dynamic> en C # 4/.NET 4 - mais à part cela, vous ne pouvez pas le faire avec exactement le code affiché car il n'y a pas de type qui soit implicitement convertible en int, string et double. (Vous pouvez écrire le vôtre, mais vous devez répertorier chaque type séparément.)

Vous pouvez utiliser Dictionary<string, object> mais il vous faudrait ensuite lancer les résultats:

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

Vous pouvez également rendre la méthode Get générique:

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

Vous pourriez déclarer un dictionnaire contenant uniquement le type object, puis lancer vos résultats; .par exemple.

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

Cependant, ce n'est pas si élégant. Si vous savez que vous allez toujours stocker l'âge, le nom, bmi, je créerais un objet pour les encapsuler et les stocker à la place. Par exemple.

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

Et puis utilisez cette information du dictionnaire ... par exemple.

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

int age = person1.Age;

etc.

23
Steve Haigh

Pourquoi ne pas utiliser:

Dictionary<string, object>

Vous pouvez créer une méthode d'extension pour les caster lorsque vous les obtenez:

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

Étant donné que vous ne voulez pas d'une collecte de données fortement typée, j'aurais pensé qu'un HashTable conviendrait à votre situation. Vous pouvez également créer une méthode d'extension pour cela, comme une autre affiche suggérée pour l'implémentation du dictionnaire.

Par exemple.

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

Votre code ressemblerait alors à:

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

c'est peut-être une vieille question, mais je m'adresse aux gars qui viennent ici pour trouver la réponse

si la valeur n'est pas un type fixe, l'un des choix utilise Hashtable veuillez regarder l'implémentation de Dictionary et 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
  {
   ...
  }

comme il ressort plus clairement des extraits de code ci-dessus, les deux implémentent littéralement les mêmes interfaces mais dans Hashtable, il n'y a pas de type sur les deux clés et valeurs car les deux sont considérés comme des objets intrinsèques, comme par exemple, vous pouvez le voir dans la méthode add dans Hashtable:

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

donc pour les cas de clés et/ou de valeurs non fixes, je recommande d'utiliser Hashtable, donc vous n'avez pas besoin d'ajouter des méthodes d'extension supplémentaires ou de remplacer le comportement par défaut.

1

Vous pouvez utiliser un Dictionary<string,object> et ensuite vous pouvez y mettre tout ce que vous voulez. Vous devrez cependant convertir les résultats au bon type lorsque vous les sortirez.

En examinant votre exemple, vous souhaiterez peut-être déterminer si une classe simple pour stocker les données pourrait être plus ce que vous voulez et permettre une meilleure sécurité de type. Cela dépend si vous avez un ensemble limité de choses à mettre dans la classe ou si vous avez besoin du stockage potentiellement illimité/inconnu d'un dictionnaire.

1
Chris

Le dictionnaire est clairement la solution la plus rapide.

Une autre façon pourrait être de stocker une classe personnalisée dans laquelle vous pourriez stocker la valeur réelle et les informations concernant son type

0
il_guru