Robusteste Equals-Implementierung für benutzerdefinierte Klassen für Wertgleichheit in C #

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

  •  05-09-2019
  •  | 
  •  

Frage

Sagen wir, ich habe eine Point2 Klasse, und ich möchte folgendes implementieren Equals:

public override bool Equals ( object obj )

public bool Equals ( Point2 obj )

Dies ist aus dem Effective C # 3 Buch:

public override bool Equals ( object obj )
{
    // STEP 1: Check for null
    if ( obj == null )
    {
        return false;
    }

    // STEP 3: equivalent data types
    if ( this.GetType ( ) != obj.GetType ( ) )
    {
        return false;
    }
    return Equals ( ( Point2 ) obj );
}

public bool Equals ( Point2 obj )
{
    // STEP 1: Check for null if nullable (e.g., a reference type)
    if ( obj == null )
    {
        return false;
    }
    // STEP 2: Check for ReferenceEquals if this is a reference type
    if ( ReferenceEquals ( this, obj ) )
    {
        return true;
    }
    // STEP 4: Possibly check for equivalent hash codes
    if ( this.GetHashCode ( ) != obj.GetHashCode ( ) )
    {
        return false;
    }
    // STEP 5: Check base.Equals if base overrides Equals()
    System.Diagnostics.Debug.Assert (
        base.GetType ( ) != typeof ( object ) );

    if ( !base.Equals ( obj ) )
    {
        return false;
    }

    // STEP 6: Compare identifying fields for equality.
    return ( ( this.X.Equals ( obj.X ) ) && ( this.Y.Equals ( obj.Y ) ) );
}

Ist das ein viel des Guten?

War es hilfreich?

Lösung

Unterstützung Gleichheit mit einer Vererbungshierarchie ist schwierig. Sie müssen genau herausfinden, was Sie meinen. Haben Sie wirklich Vererbung hier brauchen? Wenn nicht - wenn Point2 direkt von System.Object ableitet, und Sie können es versiegelt machen, wird das Leben ein bisschen leichter. In diesem Fall würde ich verwenden:

public override bool Equals (object obj)
{
    return Equals(obj as Point2);
}

public bool Equals (Point2 obj)
{
    // STEP 1: Check for null if nullable (e.g., a reference type)
    // Note use of ReferenceEquals in case you overload ==.
    if (object.ReferenceEquals(obj, null))
    {
        return false;
    }

    // STEP 2: Check for ReferenceEquals if this is a reference type
    // Skip this or not? With only two fields to check, it's probably
    // not worth it. If the later checks are costly, it could be.
    if (object.ReferenceEquals( this, obj))
    {
        return true;
    }

    // STEP 4: Possibly check for equivalent hash codes
    // Skipped in this case: would be *less* efficient

    // STEP 5: Check base.Equals if base overrides Equals()
    // Skipped in this case

    // STEP 6: Compare identifying fields for equality.
    // In this case I'm using == instead of Equals for brevity
    // - assuming X and Y are of a type which overloads ==.
    return this.X == obj.X && this.Y == obj.Y;
}

Andere Tipps

Nicht wirklich - Sie Buchhaltung für so ziemlich jede Möglichkeit. Wenn dieser Code für etwas anderes als einen Kratzer Anwendung ist, sollten Sie die Vorteile dieses Ansatzes betrachten, weil logische Fehler aufgrund seltsamen Objekts Gleichheit Verhalten schmerzhaft sind, zu debuggen.

scheint mir, wie genau das, was Sie wollen. Der ganze Block läuft darauf hinaus:

"wenn es genau die gleiche Instanz ist, true zurück. Wenn sie separate Instanzen mit der gleichen X- und Y-Werten sind, return true. In allen anderen Fällen (null, verschiedene Arten, verschiedene x / y-Werte) false zurück."

Sein sicherlich mehr Code als Ich würde schreiben will für ein Verfahren entspricht. Es gibt eine Menge redundanter Kontrollen wie etwa die Überprüfung für Reference und Hashcodes (Ich weiß, dass diese Kontrollen überflüssig sind, weil die letzten Zeilen in Ihrer Funktionskontrolle für die strukturelle Gleichheit). Konzentrieren Sie sich auf Code, der einfach und lesbar ist.

public bool Equals(object o)
{
    Point2 p = o as Point2;
    if (o != null)
        return this.X == o.X && this.Y == o.Y;
    else
        return false;
}

Da Ihre Methode equals strukturelle Gleichheit verwendet, stellen Sie sicher, dass Sie GetHashCode überschreiben mit einer Implementierung auf der Grundlage Ihrer Felder als auch.

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