Was ist die „beste“ kanonische Implementierung von Equals () für Referenz-Typen?

StackOverflow https://stackoverflow.com/questions/74514

  •  09-06-2019
  •  | 
  •  

Frage

Die Implementierung Equals () für Referenztypen ist schwieriger als es scheint. Meine aktuelle kanonische Implementierung geht so:

public bool Equals( MyClass obj )
{
  // If both refer to the same reference they are equal.
  if( ReferenceEquals( obj, this ) )
    return true;

  // If the other object is null they are not equal because in C# this cannot be null.
  if( ReferenceEquals( obj, null ) )
   return false;

   // Compare data to evaluate equality    
   return _data.Equals( obj._data );
}

public override bool Equals( object obj )
{
  // If both refer to the same reference they are equal.
  if( ReferenceEquals( obj, this ) )
    return true;

  // If the other object is null or is of a different types the objects are not equal. 
  if( ReferenceEquals( obj, null ) || obj.GetType() != GetType() )
    return false;

  // Use type-safe equality comparison
  return Equals( (MyClass)obj );
}

public override int GetHashCode()
{
  // Use data's hash code as our hashcode  
  return _data.GetHashCode();
}

Ich glaube, das gilt für alle Ecke (Vererbung und so weiter) Fälle, aber ich kann falsch sein. Was denkt ihr?

War es hilfreich?

Lösung

Ich schrieb einen ziemlich umfassenden Leitfaden für diese eine Weile zurück. Für ein Ihre equals Implementierungen beginnen sollte (das heißt die Überlastung ein Objekt einnehmen, sollte ein stark typisierte Objekt nehmen, um auf den einem Pass) geteilt werden. Zusätzlich müssen Sie Dinge beachten, wie Ihr Objekt soll wegen der Notwendigkeit, unveränderlich sein GetHashCode außer Kraft zu setzen. Mehr Infos hier:

http://gregbeech.com/blog/implementing-object-equality -in-dotnet

Andere Tipps

Bessere Hoffnung, dass this._data nicht null ist, wenn es auch ein Referenztyp.

public bool Equals( MyClass obj )
{
    if (obj == null) {
        return false;
    }
    else {
        return (this._data != null && this._data.Equals( obj._data ))
                         || obj._data == null;
    }
}

public override bool Equals( object obj )
{
    if (obj == null || !(obj is MyClass)) {
        return false;
    }
    else {
        return this.Equals( (MyClass)obj );
    }
}

public override int GetHashCode() {
    return this._data == null ? 0 : this._data.GetHashCode();
}

In Bezug auf Vererbung, ich glaube, Sie sollten nur das OO-Paradigma hat seine Magie lassen.

Insbesondere sollte die GetType() Prüfung entfernt werden, könnte es Polymorphismus auf der ganzen Linie brechen.

ich mit chakrit einverstanden sind, sollten Objekte unterschiedlicher Typen erlaubt sein, damit sie semantisch gleich, wenn sie die gleichen Daten oder ID haben.

Ich persönlich verwende folgende Möglichkeiten:

    public override bool Equals(object obj)
    {
        var other = obj as MyClass;
        if (other == null) return false;

        return this.data.Equals(other.data);
    }

Es hängt davon ab, ob Sie einen Werttyp oder einen Referenztyp sind zu schreiben. Für eine sortierbare Werttyp, empfehle ich folgendes: ein Code-snippet für Visual Studio 2005, die ein Skelett Wert Typ Rahmen-Design-Richtlinien die Einhaltung implementiert

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top