2011-01-07 6 views
1

Ich plane, mehrere Namen-indizierte Wörterbücher in einem Projekt zu verwenden. Meine erste Wahl war die Verwendung eines Schlüssels string, der nur die Name-Eigenschaft meiner Value Elemente ist.Typ Sicherheit für Dictionary-Schlüssel?

Allerdings macht dies der Dictionary-Schlüssel identisch, obwohl sie verschiedene Arten zugreifen:

private Dictionary<string, Foo> myFoos; 
private Dictionary<string, Bar> myBars; 

myFoos[bar.Name]; // shouldn't be able to do this! 

würde ich die Schlüssel wie Typ-nicht miteinander kompatibel sein, um sie unmöglich zu machen, miteinander zu verwechseln:

private Dictionary<FooName, Foo> myFoos; 
private Dictionary<BarName, Bar> myBars; 

Da eine *Name Klasse für jede Value Art zu schaffen Overkill ist, habe ich eine Name<T> Klasse:

public struct Name<T> 
{ 
    public string Name; 

    // for convenience, could be explicit instead 
    static implicit operator string(Name<T> name) 
    { 
     return name.Name; 
    } 
} 

die mir

private Dictionary<Name<Foo>, Foo> myFoos; 
private Dictionary<Name<Bar>, Bar> myBars; 

geben würde, und dann konnte ich Name<Foo> Instanzen anstelle von Strings speichern.

Das scheint ein bisschen unhandlich, aber es ist das Beste, was ich bisher gefunden habe - irgendwelche Vorschläge, wie man es besser macht?
Ist das fehlgeleitet oder genial?

Antwort

4

Die erste Frage ist:

würde ich die Schlüssel wie Typ-nicht miteinander kompatibel zu sein, um sie unmöglich zu machen, miteinander zu verwechseln:

Warum? Gibt es tatsächlich eine Chance der Verwirrung? Dies ist nicht offensichtlich. Wohlgemerkt, ich sage nicht, dass deine Methode schlecht ist; In der Tat, tatsächlich gibt es wahrscheinlich echte Vorteile daraus. Aber bedenken Sie Array-Indexer:

Die Typen der Arrays sind inkompatibel, beide verwenden ganzzahlige Indizes. Und ja, kann dies tatsächlich zu Problemen führen, wenn die Indizes verwirrt sind - wahrscheinlich die gleichen Arten von Problemen, die Sie mit Ihren Schlüsseln konfrontiert sind.

Also dieser Fall ist genau analog zu Ihrem. Vielleicht ist es gar nicht so schlecht, die gleichen Schlüsseltypen für verschiedene Container zu verwenden (obwohl Sie theoretisch recht haben und die Gefahr der Verwirrung besteht).

+0

Das Problem tritt auf, wenn ich die Liste der Bars, die einem Foo gehören, speichern möchte. Anstatt eine zweite Kopie der Bars zu speichern, speichere ich die Bar.Name - und eine Dictionary > beginnt zu schlammigen Gewässern. – mskfisher

+0

@mskfisher: das ist ein schlechter Ansatz. * Speichern Sie die Bars direkt, nicht nur ihre Namen! Das ist * nicht * das Erstellen von Kopien (es sei denn, Ihre Foos und Bars sind Strukturen, die sie in diesem Fall nicht sein sollten). Wenn es sich um Klassen handelt, werden Ihre Kopien keine Kopien erstellen, sondern nur Verweise auf die Objekte. Dies ist eine fundamentale Eigenschaft der Objektorientierung und Ihr Anwendungsfall ist so üblich, dass er einen eigenen Namen hat: [aggregation] (http://en.wikipedia.org/wiki/Object_composition). –

+0

@Konrad: Guter Fang, und eine andere Sache hätte ich erwähnen sollen. Ich habe bei diesem Design zwischen Structs und Klassen hin und her gegangen, da ich Kopien zwischen Threads nach Wert, nicht nach Referenz übergeben möchte. Ich bin jetzt dabei, nur mit Klassen zu gehen und den Kopierkonstruktor für jeden Typ zu erstellen, den ich zwischen Threads übergeben muss. – mskfisher

5

Das funktioniert, außer dass Sie Equals und GetHashCode überschreiben müssen, um die Namen nach Wert zu vergleichen.

Verwandte Themen