| 

.NET C# Java Javascript Exception

4
Mit Dictionary<string, int> kann man string auf int übersetzen. Wie kann ich als Schlüssel eine eigene Klasse Name { string Vorname; string Nachname; } verwenden? Das Dictionary scheint das nicht zu begreifen.
14.09.2009
alf-vom-mars 81 2
4 Antworten
2
Ich hab kurzem einen Artikel über so etwas geschrieben. Bezieht sich allerdings direkt auf das HashSet - das Dictionary arbeitet gleich und somit gilt das geschriebenen auch für das Dictionary. Guckst du: HashSet<T> und eigene Typen

Wichtig ist folgender Hinweis aus der MSDN:
Wenn ein Objekt im Dictionary<(Of <(TKey, TValue>)>) als Schlüssel verwendet wird, darf es nicht auf eine Weise geändert werden, die sich auf seinen Hashwert auswirkt. Jeder Schlüssel in einem Dictionary<(Of <(TKey, TValue>)>) muss für den Gleichheitsvergleich des Wörterbuches eindeutig sein. Wenn der Werttyp TValue ein Referenztyp ist, kann ein Wert nullNothingnullptrNULL-Verweis (Nothing in Visual Basic) sein, ein Schlüssel jedoch nicht.

Dictionary<(Of <(TKey, TValue>)>) erfordert eine Gleichheitsimplementierung, um zu bestimmen, ob Schlüssel gleich sind. Sie können mithilfe eines Konstruktors, der einen comparer-Parameter akzeptiert, eine Implementierung der generischen IEqualityComparer<(Of <(T>)>)-Schnittstelle angeben. Andernfalls wird der generische Standardgleichheitsvergleich EqualityComparer<(Of <(T>)>)..::.Default verwendet. Wenn der Typ TKey die generische System..::.IEquatable<(Of <(T>)>)-Schnittstelle implementiert, verwendet der Standardgleichheitsvergleich diese Implementierung.
14.09.2009
gfoidl 9,4k 3 5
gfoidl 9,4k 3 5
1
Meiner Meinung nach geht das (wenn ich die Frage richtig verstanden habe), erst mal ohne Überschreiben von GetHashCode und Equals. Allerdings muss die Instanz beibehalten werden.

Person a1 = new Person() { Nachname = "A", Vorname = "1" };
Person b2 = new Person() { Nachname = "B", Vorname = "2" };

Dictionary<Person, String> personen = new Dictionary<Person, string>();
personen.Add(a1, "Person 1");
personen.Add(b2, "Person 2");

// Ausgabe "Person 2"
Console.WriteLine(personen[b2]);
// Fehler (KeyNotFoundException) mit ...
Console.WriteLine(personen[new Person() { Nachname = "B", Vorname = "2" }]);

Ansonsten würde ich analog eine Key Funktion für die Person definieren wie bereits beschrieben um einen String als Key für ein Objekt zu erhalten. Dabei beachten, dass ein sinnvolles Trennzeichen verwendet wird um einen eindeutigen Key zu erhalten.

Das Überschreiben der GetHashCode (und Equals über Implementierung von IEqualityComparer)Funktion finde ich an dieser Stelle aufwendiger (weil in GetHashCode eindeutig ein int ermittelt werden muss). Das Prinzip ist gleich (Beispiel hier nur mit GetHashCode)...

Dictionary<int, string> personen = new Dictionary<int, string>();
personen.Add(a1.GetHashCode(), "Person 1");
personen.Add(b2.GetHashCode(), "Person 2");
// jetzt ohne Fehler korrektes Ergebnis, wenn HashCode eindeutig
Console.WriteLine(personen[new Person() { Nachname = "B", Vorname = "2" }.GetHashCode()]);
14.09.2009
me 1,1k 2 9
me 1,1k 2 9
Hast du die anderen Antworten schon gelesen? Die Instanz muss nämlich nicht gehalten werden - nur der HashCode und Equals müssen gleich sein (dann kann es auch eine andere Instanz sein die für das Dictionary als gleich erachtet wird).

BTW: Ein Dictionary würde ich nicht mit 'list' bezeichnen.
gfoidl 14.09.2009
Das obere Beispiel berücksichtigt nicht die Anpassung von GetHashCode oder Equals, sondern verwendet die Standardbehandlung.
Was die Benennung betrifft stimme ich zu, ich werde die Antwort entsprechend anpassen.
me 15.09.2009
0
Ob man eine eigene Klasse für Keys hinterlegen kann ist mir nicht bekannt.
Aber als Alternative kannst du ja deinen Vornamen und Nachnamen in einen String kombinieren.

Zum Beispiel:

"Max" "Mustermann" wird zu "Max#Mustermann" oder "Mustermann#Max" als Key.

Dadurch kannst du dann den jeweiligen Wert aus deinem Directory auslesen ;-)

Grüßle
14.09.2009
Scout 1,4k 2 8
Scout 1,4k 2 8
0
Das ist alles eine Frage des Überschreibens der Methode "GetHashCode", über die normalerweise ein "Eindeutiger Schlüssel" für ein Objekt zurückgegeben wird. Dieser ist dann insofern eindeutig, als ein Objekt mit gleichen Daten auch den gleichen Hash Code zurückgeben wird.

Dieser Hash Code wird vom Dictionary verwendet, um herauszufinden, welcher Eintrag gemeint ist.

Bitte beachten: Es empfiehlt sich stark, wenn man eine Methode aus dem Bunde GetHashCode/Equals/ToString überschreibt auch die anderen beiden Methoden zu überschreiben. Also in Deinem Fall solltest Du mindestens GetHashCode und Equals überschreiben, damit die Gleichheit für Deine Klasse vernünftig geprüft werden kann.
14.09.2009
balu 216 1 3
Nich nur der HashCode sonder auch Equals. Daher finde ich es besser gleich IEquatable<T> zu implementieren.
gfoidl 14.09.2009

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH