2011-01-04 13 views
15

diese Klasse verwendenC# Hashset enthält nicht eindeutige Objekte

public class Foo 
{ 
    public string c1, c2; 

    public Foo(string one, string two) 
    { 
     c1 = one; 
     c2 = two; 
    } 

    public override int GetHashCode() 
    { 
     return (c1 + c2).GetHashCode(); 
    } 
} 

Und dieses HashSet

HashSet<Foo> aFoos = new HashSet<Foo>(); 
Foo aFoo = new Foo("a", "b"); 

aFoos.Add(aFoo); 
aFoos.Add(new Foo("a", "b")); 

label1.Text = aFoos.Count().ToString(); 

ich die Antwort 2, erhalten, wenn sollte es doch 1 sein Gibt es eine Möglichkeit, dies zu beheben Mein HashSet enthält also nur eindeutige Objekte?

Danke, Asche.

+6

Sie haben 'Equals' nicht überschrieben. – Ani

Antwort

25

Der HashSet<T> Typ ultamitely verwendet Gleichheit, um zu bestimmen, ob zwei Objekte gleich sind oder nicht. Im Typ Foo haben Sie nur GetHashCode und nicht Gleichheit überschrieben. Dies bedeutet, dass die Gleichheitsprüfungen standardmäßig auf Object.Equals zurückgesetzt werden, wobei die Referenzgleichheit verwendet wird. Dies erklärt, warum Sie mehrere Elemente in der HashSet<Foo> sehen.

Um dies zu beheben, müssen Sie Equals im Foo Typ überschreiben.

public override bool Equals(object obj) { 
    var other = obj as Foo; 
    if (other == null) { 
    return false; 
    } 
    return c1 == other.c1 && c2 == other.c2; 
} 
+3

+1, weil es korrekt ist, aber man kann hinzufügen, dass die von 'GetHashCode' zurückgegebenen Hashes für unterschiedliche Werte kollidieren dürfen, weshalb der Vergleich des Hash-Codes nicht die Gleichheit von Objekten im Allgemeinen sicherstellt. – Lucero

7

Sie müssen Equals Methode überschreiben. Nur GetHashCode ist nicht genug.

4

Sie müssen auch die equals-Methode überschreiben. Der Grund dafür ist, dass der Hashcode für zwei Objekte kollidieren kann, die nicht gleich sind. Sonst wird es nicht funktionieren.

public override bool Equals(Object obj) 
{ 
    Foo otherObject = obj as Foo; 
    return otherObject != null && otherObject.c1 == this.c1 && otherObject.c2 == this.c2; 
} 
+0

Der Ausdruck 'local.Equals (null)' sollte 'false' nicht' true' zurückgeben. – JaredPar

+0

Wahr, ich habe es einfach zu schnell für mich selbst geschrieben :). –

Verwandte Themen