2012-04-14 7 views
0

ich eine Klasse, die ähnlich wie diese ist:Hashset meiner Klasse nicht Ausgabe enthält

public class Int16_2D 
{ 
    public Int16 a, b; 

    public override bool Equals(Object other) 
    { 
     return other is Int16_2D && 
     a == ((Int16_2D)other).a && 
     b == ((Int16_2D)other).b; 
    } 
} 

Dies funktioniert in HashSet<Int16_2D>. In Dictionary<Int16_2D, myType> gibt .ContainsKey jedoch false zurück, wenn dies nicht der Fall ist. Fehle ich etwas in meiner Implementierung von ==?

+2

http://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when-equals-method-is-overriden-in-c –

+2

Beachten Sie, dass Sie nicht wirklich sind Die Implementierung von '==', 'Equals()' ist etwas anderes. – svick

Antwort

2

Sie müssen GetHashCode() überschreiben. Die Tatsache, dass es mit HashSet<T> funktioniert, ist wahrscheinlich nur ein glücklicher Zufall.

Beide Sammlungen verwenden den aus GetHashCode ermittelten Hash-Code, um einen Bucket (dh eine Liste von Objekten) zu finden, in dem das Objekt platziert werden soll. Dann durchsucht es diesen Bucket, um das Objekt zu finden, und verwendet Equals, um die Gleichheit sicherzustellen. Dies gibt die schönen schnellen Sucheigenschaften von Dictionary und HashSet. Dies bedeutet jedoch auch, dass wenn GetHashCode nicht überschrieben wird, so dass es den Typen Equals Methode entspricht, Sie ein solches Objekt in einer der Sammlungen nicht finden können.

Sie sollten fast immer sowohl GetHashCode als auch Equals oder keine davon implementieren.

0

Sie müssen GetHashCode außer Kraft setzen, damit das Wörterbuch funktioniert.

0

Sie müssen auch GetHashCode() überschreiben - dies geht Hand in Hand mit dem Überschreiben Equals. Das Wörterbuch verwendet GetHashCode(), um zu bestimmen, in welchen Bereich ein Wert fallen würde - nur wenn ein passendes Element in diesem Bereich gefunden wird, prüft es die tatsächliche Gleichheit der Elemente.

3

Damit eine Klasse in einer Hashtabelle oder einem Wörterbuch arbeiten kann, müssen Sie GetHashCode() implementieren! Ich habe keine Ahnung, warum es in HashSet funktioniert; Ich denke, es war nur Glück.

Beachten Sie, dass es gefährlich ist, muable Felder für die Berechnung von Equals oder GetHashCode() zu verwenden. Warum? Bedenken Sie:

var x = new Int16_2D { a = 1, b = 2 }; 
var set = new HashSet<Int16_2D> { x }; 

var y = new Int16_2D { a = 1, b = 2 }; 
Console.WriteLine(set.Contains(y)); // True 

x.a = 3; 
Console.WriteLine(set.Contains(y)); // False 
Console.WriteLine(set.Contains(x)); // Also false! 

Mit anderen Worten, wenn Sie setzen x.a = 3; Sie ändern Hash-Code des x. Aber die x-Position in der Hash-Tabelle basiert auf seinem alten Hash-Code, so dass x im Grunde jetzt verloren ist. Sehen Sie dies in Aktion bei http://ideone.com/QQw08

Auch, wie svick Notizen, Implementierung Equals implementiert nicht ==. Wenn Sie nicht == implementieren, die == wird von einem Operator eine Referenz Vergleich liefern, so:

var x = new Int16_2d { a = 1, b = 2 }; 
var y = new Int16_2d { a = 1, b = 2 }; 
Console.WriteLine(x.Equals(y));    //True 
Console.WriteLine(x == y);     //False 

Abschließend sind Sie besser dran dies eine unveränderliche Art zu machen; Da es nur 4 Bytes lang ist, würde ich es wahrscheinlich zu einer unveränderlichen Struktur machen.