Ich bin mir der Tatsache bewusst, dass ich immer Equals(object)
und GetHashCode()
bei der Implementierung IEquatable<T>.Equals(T)
übersteuern muss.Warum gewinnt Equals (Objekt) Equals (T), wenn ein geerbtes Objekt in Hashset oder anderen Auflistungen verwendet wird?
Allerdings verstehe ich nicht, warum in einigen Situationen die Equals(object)
gewinnt über die generische Equals(T)
.
Zum Beispiel warum passiert folgendes? Wenn ich für eine Schnittstelle IEquatable<T>
deklariere und dafür einen konkreten Typ X
implementiere, wird der generelle Equals(object)
durch einen Hashset<X>
aufgerufen, wenn solche Items miteinander verglichen werden. In allen anderen Situationen, in denen mindestens eine der Seiten in das Interface umgewandelt wurde, wird das korrekte Equals(T)
aufgerufen.
Hier ist ein Code-Beispiel zu demonstrieren:
public interface IPerson : IEquatable<IPerson> { }
//Simple example implementation of Equals (returns always true)
class Person : IPerson
{
public bool Equals(IPerson other)
{
return true;
}
public override bool Equals(object obj)
{
return true;
}
public override int GetHashCode()
{
return 0;
}
}
private static void doEqualityCompares()
{
var t1 = new Person();
var hst = new HashSet<Person>();
var hsi = new HashSet<IPerson>();
hst.Add(t1);
hsi.Add(t1);
//Direct comparison
t1.Equals(t1); //IEquatable<T>.Equals(T)
hst.Contains(t1); //Equals(object) --> why? both sides inherit of IPerson...
hst.Contains((IPerson)t1); //IEquatable<T>.Equals(T)
hsi.Contains(t1); //IEquatable<T>.Equals(T)
hsi.Contains((IPerson)t1); //IEquatable<T>.Equals(T)
}
sollte nicht 'hst.Contains ((IPerson) t1);' nicht kompilieren? –
@Dennis_E Siehe die zweite Hälfte meiner Antwort. – Servy
@Dennis_E: Das ist nicht 'HashSet .Contains' aber' Enumerable.Contains', die die Schnittstelle akzeptiert. Dies ist also die langsame Version, die alle Elemente aufzählt und sie mit 'Equals (IPerson sony) 'vergleicht, anstatt' GetHashCode' zu verwenden. –