C # Dictionary und veränderbare Schlüssel

8

Mir wurde gesagt, dass einer der vielen Gründe, warum Strings in der C # -Spezifikation unveränderlich gemacht wurden, das Problem von Hashtables war, deren Schlüssel geändert wurden, wenn Verweise auf die String-Schlüssel ihren Inhalt änderten.

Das Wörterbuch & lt; & gt; type erlaubt die Verwendung von Referenztypen als Schlüssel. Wie vermeidet das Wörterbuch das Problem veränderter Schlüssel, die zu "falschen" Werten führen? Gibt es einen Memberly-Clone, der aus einem Objekt besteht, wenn er als Schlüssel verwendet wird?

    
Pierreten 09.06.2010, 15:30
quelle

5 Antworten

9

Der Typ Dictionary<TKey,TValue> versucht nicht davor zu schützen, dass der Benutzer den verwendeten Schlüssel ändert. Es bleibt dem Entwickler überlassen, dafür verantwortlich zu sein, dass er den Schlüssel nicht mutiert.

Wenn du ein bisschen darüber nachdenkst, ist das wirklich der einzig vernünftige Weg Dictionary<TKey,TValue> kann dauern. Betrachten Sie die Implikation, eine Operation wie einen Memberwise-Klon für das Objekt auszuführen. Um gründlich zu sein, müssen Sie einen tiefen Klon erstellen, da ein Objekt, auf das im Schlüssel verwiesen wird, ebenfalls mutiert werden kann und somit den Hash-Code beeinflusst. So wird nun bei jedem in der Tabelle verwendeten Schlüssel das vollständige Objektdiagramm kloniert, um vor Mutationen zu schützen. Dies wäre sowohl fehlerhaft als auch möglicherweise eine sehr teure Operation.

    
JaredPar 09.06.2010, 15:33
quelle
8

Wenn Sie einen veränderbaren Referenztyp als Schlüssel verwenden, garantiert die Standardimplementierung von GetHashCode() die Hash-Gleichheit unabhängig vom Objektstatus (d. h. der Hash ist an die Referenz und nicht an den Status gebunden). Sie haben jedoch Recht, dass ein veränderbarer Typ mit Semantik der Wertgleichheit (wobei GetHashCode vermutlich vom Status abhängt) eine schlechte Wahl für einen Wörterbuchschlüssel ist.

    
Dan Bryant 09.06.2010 16:16
quelle
5

Die Klasse Dictionary<> schützt sich nicht vor einem veränderbaren Schlüsselobjekt, das geändert wird. Es liegt an Ihnen zu wissen, ob die Klasse, die Sie als Schlüssel verwenden, änderbar ist und wenn möglich, zu vermeiden.

    
JSBձոգչ 09.06.2010 15:32
quelle
3

Es vermeidet diese Situation nicht. Es liegt an dem aufrufenden Code, dies zu erzwingen:

  

Solange ein Objekt als Schlüssel in Dictionary<TKey, TValue> verwendet wird, darf es sich in keiner Weise ändern, die sich auf seinen Hashwert auswirkt. Jeder Schlüssel in Dictionary<TKey, TValue> muss gemäß dem Gleichheitsvergleich des Wörterbuchs eindeutig sein. Ein Schlüssel kann nicht null sein, aber ein Wert kann sein, wenn der Werttyp TValue ein Referenztyp ist.

(Von MSDN )

    
Anton Gogolev 09.06.2010 15:34
quelle
3

Wenn ein Referenztyp Equals / GetHashCode nicht überschreibt, interessiert sich ein Dictionary, das den Standardkomparator verwendet, nicht für die Felder oder Eigenschaften eines Schlüsselobjekts und wird daher nicht bemerken oder sich darum kümmern, wenn sie sich ändern. Es ist am einfachsten zu denken, dass die Standardmethode GetHashCode eine Zahl zurückgibt, die sich auf eine "Objekt-ID" bezieht, und die Standard-Equals-Methode "Objekt-IDs" vergleicht. Tatsächlich könnte GetHashCode in einem System, das auf zwei Milliarden oder weniger Objekte beschränkt ist, einfach eine Objekt-ID zurückgeben, aber aus verschiedenen Gründen könnte es auch andere Dinge tun.

Wenn der einzige Teil eines Objekts, der von Equals oder GetHashCode untersucht wird, die Objekt-ID ist, dann sind alle Objekte für diese Funktionen unveränderlich. Sobald ein Objekt erstellt wurde, hat es immer die gleiche ID, und diese ID wird niemals für ein anderes Objekt verwendet, bis alle Spuren der früheren Objekt-ID aus dem Universum verschwunden sind.

    
supercat 30.09.2011 14:54
quelle

Tags und Links