2012-02-08 2 views
3

en C# Je dois conserver les données dans un objet dictionnaire, ressemble à:En utilisant un dictionnaire <string, object> comme Dictionnaire <string, Dictionnaire <string, string >>

Dictionary<string, Dictionary<string, string>> MyDict = 
    new Dictionary<string, Dictionary<string, string>>(); 

Maintenant, je me suis rendu, que Dans certains cas, j'aurais besoin d'autres données (pas de type dictionnaire) comme valeur de la dictée principale.

Y at-il une sorte de problème ou de limitation, si je prends juste le dict principal. comme:

Dictionary<string, object> MyDict = new Dictionary<string, object>(); 

dans le champ objet que je pourrais mettre la chaîne, le dictionnaire, quel que soit ..

Merci à l'avance, Cordialement, Steven

+0

le titre ne correspond pas au texte de votre question – vulkanino

+0

je n » Je pense que ce serait un problème. Vous auriez probablement juste besoin de le lancer comme ce qu'il est supposé être quand vous y accédez. – Kevin

+0

Vous pouvez voir la réponse à cette question http://stackoverflow.com/questions/569903/multi-value-dictionary est ce que vous voulez? – DotNetUser

Répondre

1

En utilisant l'objet comme valeur dans votre dictionnaire, vous encourrez des risques et des complications:

  • Le manque de sécurité de type (tout peut être réglé sur la valeur)
  • Vous devez jeter un type particulier, probablement basé sur la valeur

Vous devriez probablement repenser votre conception. Mais si vous voulez vraiment une flexibilité, vous pouvez créer un nouveau type qui fonctionnera comme type de valeur. Quelque chose comme:

class MySpecialType 
{ 
    public Dictionary<string, string> MyStringDictionary { get; set; } 
    public string MyStringVal {get; set;} 

    public Type ActiveType { get; set; } // property would specify the current type 
    // ... 

Votre principale déclaration de dictionnaire serait alors ressembler à:

Dictionary<string, MySpecialType> MyDict = new Dictionary<string, MySpecialType>(); 

Vous pouvez utiliser la propriété ActiveType ou créer un ENUM qui préciserait le type. Vous pourriez également avoir des fonctions util static dans la classe qui pourraient aider à retourner l'instance et le type ...

+0

Votre answear en combinaison avec la connaissance des autres a plus de sens pour moi. (Merci pour ça! "Le manque de sécurité de type (tout peut être réglé sur la valeur)" serait une caractéristique pour moi dans ce cas: D Votre solution avec la classe a du sens, mais c'est un peu comme la surcharge que j'ai essayé d'éviter moi. Ainsi résolu, grâce à tous, mon problème principal est le contexte et la conception du code. *** REMERCIEMENTS *** – N471v3

0

Non, il n'y a pas de problème. Si vous avez besoin de taper la valeur Dictionary<string, string> il suffit de la lancer et vous aurez cette solution.

5

Oui, votre dictionnaire ne serait pas fortement typé plus - dans la première approche que vous pourriez faire quelque chose comme:

string value = myDict["foo"]["bar"]; 

Dans la seconde approche ce n'est pas plus possible puisque vous devez jeter les premiers:

string value = ((Dictionary<string,string>)myDict["foo"])["bar"]; 

Il semble que votre problème pourrait être résolu avec une meilleure approche de conception. Habituellement, le besoin de stocker différents types d'objets dans la même structure de données peut être évité en re-concevant la solution - donc pourquoi avez-vous besoin de faire cela?

Edit:

Si vous voulez juste gérer null valeurs que vous pourriez faire quelque chose comme:

string value = myDict["foo"] != null ? myDict["foo"]["bar"] : null; 

Ou enveloppé dans une méthode d'extension:

public static T GetValue<T>(this Dictionary<T, Dictionary<T,T>> dict, 
          T key, T subKey) where T: class 
{ 
    T value = dict[key] != null ? dict[key][subKey] : null; 
    return value; 
} 

string value = myDict.GetValue("foo", "bar"); 
+0

Parce que cela est implémenté sur environ 1000 lignes de code, et dans certains cas, il était nécessaire d'ajouter des valeurs avec null, où la clé a été utilisée comme données. comme: MyDict.Add ("One_key", AnotherDictionary); MyDict.Add ("Cool_key", null); que dans la boucle for: if (MyDict.value! = Null) // faire quelque chose Et votre point est exact, le design est peut-être un peu défectueux! Mais j'ai besoin de la clé et du champ de valeur pour les données maintenant, et j'ai pensé que je ne voulais pas créer un sous-dictionnaire pour ces eintries avec une valeur nulle, à cause du code, si vous voyez ce que je veux dire. (beaucoup d'entrées avec une valeur nulle) – N471v3

+0

Merci à tous pour les réponses rapides et bonnes! – N471v3

0

Eh bien, votre code sera de type moins sécurisé et vous aurez besoin de vérifications de type à l'exécution et de lancers de type, mais sinon vous pouvez utiliser object comme un type de valeur de dictionnaire et stocker tous les types là-bas.

1

Vous perdrez les types forts et tous leurs avantages.

Pouvez-vous pas créer une nouvelle classe qui a une propriété dictionnaire et ajoutez vos autres données à elle:

public class CallItWhatYouLike 
{ 
    public Dictionary<string, string> Dictionary {get; set;} 
    public int AnotherProperty {get; set;} 
    ... 
} 

var MyDict = new Dictionary<string, CallItWhatYouLike>(); 
0

Vous devrez payer une pénalité de performance lorsque vous unbox le System.Object, mais à part qu'il y ISN » t un problème avec votre approche autre que la coulée excessive pour les indexeurs (en raison d'un faible typage).

Vous pouvez envisager d'utiliser un System.Tuple si vous utilisez .NET 4.

4

Vous pouvez le faire. Après la récupération de données à partir du dictionnaire principal, vous devrez jeter le résultat à un type approprié:

object obj; 
If(mainDict.TryGetValue("key", out obj)) { 
    var dict = obj as Dictionary<string, string>>; 
    if (dict != null) { 
     // work with dict 
    } else { 
     var value = obj as MyOtherType; 
     .... 
    } 
} 

Mais notez que c'est le type-safe; c'est-à-dire que le compilateur ne peut vérifier que partiellement la validité de votre code en ce qui concerne les valeurs du type object.


Sinon, vous pouvez essayer une solution plus

public abstract class MyBaseClass 
{ 
    public abstract void DoSomething(); 
} 

public class MyDictClass : MyBaseClass 
{ 
    public readonly Dictionary<string, string> Dict = new Dictionary<string, string>(); 

    public override void DoSomething() 
    { 
     // So something with Dict 
    } 
} 

public class MyTextClass : MyBaseClass 
{ 
    public string Text { get; set; } 

    public override void DoSomething() 
    { 
     // So something with Text 
    } 
} 

orienté objet déclarer ensuite votre dictionnaire principal avec

var mainDict = new Dictionary<string, MyBaseClass>(); 

mainDict.Add("x", new MyDictClass()); 
mainDict.Add("y", new MyTextClass()); 

... 

MyBaseClass result = mainDict[key]; 
result.DoSomething(); // Works for dict and text! 
Questions connexes