2008-08-12 6 views
69

Donc, je me suis un peu fourré avec C# récemment, et toutes les collections génériques m'ont un peu confus. Dire que je voulais représenter une structure de données où la tête d'un arbre était une paire valeur/clé, puis une liste facultative de paires de valeurs clés en dessous (mais pas plus de niveaux). Serait-ce approprié?Meilleure implémentation pour la structure de données de paires de valeurs clés?

public class TokenTree 
{ 
    public TokenTree() 
    { 
     /* I must admit to not fully understanding this, 
     * I got it from msdn. As far as I can tell, IDictionary is an 
     * interface, and Dictionary is the default implementation of 
     * that interface, right? 
     */ 
     SubPairs = new Dictionary<string, string>(); 
    } 

    public string Key; 
    public string Value; 
    public IDictionary<string, string> SubPairs; 
} 

Ce n'est vraiment qu'un simple shunt pour transmettre des données.

Répondre

132

Il y a un type de données réel appelé KeyValuePair, utilisez comme celui-ci

KeyValuePair<string, string> myKeyValuePair = new KeyValuePair<string,string>("defaultkey", "defaultvalue"); 
+1

Cela fonctionne très bien avec une instruction "using" (similaire à l'ancien typedef) afin d'économiser un peu de frappe et de rendre tout plus clair. Si vous utilisez constamment e. g. la paire (chaîne, chaîne). –

+8

KeyValuePair NAME_HERE = new KeyValuePair ("defaultkey", "defaultvalue"); – HasanAboShally

+1

Pour développer le commentaire de @AndreasReiff: 'using NameValuePair = System.Collections.Generic.KeyValuePair ;' près du début de chaque fichier nécessitant une structure '(chaîne, chaîne)'. Bien que je trouvais plus commode de créer une classe NameValuePair dans mon espace de noms: 'public class NameValuePair \t { \t \t KeyValuePair it; \t \t NameValuePair public (nom de chaîne, valeur de chaîne) \t \t { \t \t \t it = nouveau KeyValuePair (nom, valeur); Public string Nom {get {return it.Key; }} \t \t public string Valeur {get {return it.Value; }} \t} ' – ToolmakerSteve

1

Dictionary Class est exactement ce que vous voulez, correct.

Vous pouvez déclarer le champ directement en tant que dictionnaire, au lieu de IDictionary, mais c'est à vous de décider.

5

Il existe un type intégré KeyValuePair. En fait, c'est ce à quoi l'IDictionary vous donne accès lorsque vous l'itérez.

En outre, cette structure est à peine un arbre, trouver un nom plus représentatif pourrait être un bon exercice.

12

Une chose possible, vous pouvez faire est d'utiliser l'objet Dictionary tout droit sorti de la boîte, puis simplement l'étendre avec vos propres modifications:

public class TokenTree : Dictionary<string, string> 
{ 
    public IDictionary<string, string> SubPairs; 
} 

Cela vous donne l'avantage de ne pas avoir à faire respecter les règles de IDictionary pour votre clé (par exemple, l'unicité de la clé, etc).

Et yup vous avez le concept du constructeur droite :)

2

@Jay Mooney: Une classe Dictionnaire générique dans .NET est en fait une table de hachage, juste avec des types fixes.

Le code que vous avez montré ne devrait pas convaincre quiconque d'utiliser Hashtable au lieu du dictionnaire, puisque les deux morceaux de code peuvent être utilisés pour les deux types.

Pour Hashtable:

foreach(object key in h.keys) 
{ 
    string keyAsString = key.ToString(); // btw, this is unnecessary 
    string valAsString = h[key].ToString(); 

    System.Diagnostics.Debug.WriteLine(keyAsString + " " + valAsString); 
} 

Pour le dictionnaire:

foreach(string key in d.keys) 
{ 
    string valAsString = d[key].ToString(); 

    System.Diagnostics.Debug.WriteLine(key + " " + valAsString); 
} 

Et la même chose pour l'autre avec KeyValuePair, il suffit d'utiliser la version non générique pour Hashtable, et la version générique Dictionnaire. Hashtable utilise Object à la fois pour la clé et la valeur, ce qui signifie que vous saisissez tous les types de valeurs, et que vous n'avez pas de type de sécurité, et que Dictionary utilise des types génériques et est donc meilleur.

1

Utilisez quelque chose comme ceci:

class Tree <T> : Dictionary < T, IList< Tree <T> > > 
{ 
} 

Il est laid, mais je pense que ça va vous donner ce que vous voulez. Dommage KeyValuePair est scellé.

3

Juste une chose à ajouter à cela (même si je pense que vous avez déjà répondu à votre question par d'autres).Dans l'intérêt de l'extensibilité (puisque nous savons tous que cela arrivera à un moment donné), vous voudrez peut-être consulter le Composite Pattern Ceci est idéal pour travailler avec des "Structures arborescentes" ..

Comme je l'ai dit, je vous connais ne sont attendre d'un sous-niveau, mais cela pourrait vraiment être utile si vous avez besoin plus tard pour étendre^_^

7

Je pense que ce que vous pourriez être après (comme la mise en œuvre littérale de vous la question) est:

pubic class TokenTree 
{ 
    public TokenTree() 
    { 
     tree = new Dictionary<string, IDictionary<string,string>>(); 
    } 

    IDictionary<string, IDictionary<string, string>> tree; 
} 

Vous avez effectivement dit une "liste" de valeurs-clés dans votre question, donc vous pouvez échanger l'IDictionary intérieur avec un:

IList<KeyValuePair<string, string>> 
Questions connexes