Wie der Titel schon sagt: Muss ich den ==
Operator überschreiben ? Wie wäre es mit der .Equals()
Methode? Fehlt mir etwas?
Wie der Titel schon sagt: Muss ich den ==
Operator überschreiben ? Wie wäre es mit der .Equals()
Methode? Fehlt mir etwas?
Antworten:
Ein Beispiel aus msdn
public struct Complex
{
double re, im;
public override bool Equals(Object obj)
{
return obj is Complex c && this == c;
}
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
}
Complex other = obj as Complex
und dann zu prüfen, ob other == null
anstelle einer Verwendung is
und dann eine Besetzung ...
Complex? other = obj as Complex?
, aber nullbare Typen sind oft nicht effizient.
MyComplex
wie Sie vorschlagen.
Sie sollten auch IEquatable <T> implementieren. Hier ist ein Auszug aus den Framework Design Guidelines:
Implementieren Sie IEquatable für Werttypen. Die Object.Equals-Methode für Werttypen verursacht Boxing, und ihre Standardimplementierung ist nicht sehr effizient, da sie die Refektion verwendet. IEquatable.Equals bieten eine viel bessere Leistung und können so implementiert werden, dass kein Boxen verursacht wird.
public struct Int32 : IEquatable<Int32> {
public bool Equals(Int32 other){ ... }
}
Befolgen Sie bei der Implementierung von IEquatable.Equals die gleichen Richtlinien wie beim Überschreiben von Object.Equals. In Abschnitt 8.7.1 finden Sie detaillierte Richtlinien zum Überschreiben von Object.Equals
Leider habe ich nicht genug Ruf, um andere Einträge zu kommentieren. Daher veröffentliche ich hier eine mögliche Verbesserung der Top-Lösung.
Korrigieren Sie mich, wenn ich falsch liege, aber die oben erwähnte Implementierung
public struct Complex
{
double re, im;
public override bool Equals(Object obj)
{
return obj is Complex && this == (Complex)obj;
}
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
}
Hat einen großen Fehler. Ich beziehe mich auf
public override int GetHashCode()
{
return re.GetHashCode() ^ im.GetHashCode();
}
XORing ist symmetrisch, daher würden Complex (2,1) und Complex (1,2) denselben Hashcode ergeben.
Wir sollten wahrscheinlich mehr machen wie:
public override int GetHashCode()
{
return re.GetHashCode() * 17 ^ im.GetHashCode();
}
Meistens können Sie die Implementierung von Equals und GetHashcode in Strukturen vermeiden, da der Compiler eine automatische Implementierung für Werttypen mit bitweisem Inhalt + Reflexion für Referenzelemente durchführt.
Schauen Sie sich diesen Beitrag an: Welches ist am besten für Datenspeicher Struct / Classes geeignet?
Zur Vereinfachung der Verwendung können Sie also weiterhin == und! = Implementieren.
Meistens können Sie jedoch die Implementierung von Equals und GetHashcode vermeiden.
Ein Fall, in dem Sie Equals und GetHashCode implementieren müssten, betrifft ein Feld, das Sie nicht berücksichtigen möchten.
Zum Beispiel ein Feld, das sich im Laufe der Zeit ändert, wie das Alter einer Person oder die InstantSpeed eines Autos (die Identität des Objekts sollte sich nicht ändern, wenn Sie es wieder im Wörterbuch an derselben Stelle finden möchten).
Grüße, bester Code
Der grundlegende Unterschied zwischen den beiden besteht darin, dass der ==
Operator statisch ist, dh die geeignete aufzurufende Methode wird zur Kompilierungszeit bestimmt, während die Equals
Methode auf einer Instanz dinamisch aufgerufen wird.
Beides zu definieren ist wahrscheinlich das Beste, auch wenn dies bei Strukturen weniger wichtig ist, da Strukturen nicht erweitert werden können (eine Struktur kann nicht von einer anderen erben).
Nur zur Vervollständigung würde ich auch raten, Equals
Methode zu überladen :
public bool Equals(Complex other)
{
return other.re == re && other.im == im;
}
Dies ist eine echte Verbesserung, da das Eingabeargument der Equals(Object obj)
Methode nicht in einem Boxing auftritt
Einige bewährte Methoden für die Verwendung von Werttypen:
Dies kommt aus diesem Beitrag: http://theburningmonk.com/2015/07/beware-of-implicit-boxing-of-value-types/