Es igual a más robusta aplicación para las clases personalizadas para la igualdad de valor en C #

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

  •  05-09-2019
  •  | 
  •  

Pregunta

Decir que tengo una clase Point2, y quiero poner en práctica el siguiente es igual a:

public override bool Equals ( object obj )

public bool Equals ( Point2 obj )

Esto es del libro # 3 efectiva C:

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 ) ) );
}

¿Es una exageración?

¿Fue útil?

Solución

Apoyo a la igualdad con una jerarquía de herencia es complicado. Usted necesita saber exactamente lo que quiere decir. ¿Usted realmente necesita la herencia aquí? Si no es así - si Point2 deriva directamente de System.Object, y usted puede hacer que sea sellada, la vida se convierte en un poco más fácil. En ese caso, me gustaría utilizar:

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;
}

Otros consejos

En realidad, no - que está de contabilidad para casi todas las posibilidades. Si este código es para otra cosa que una aplicación de cero debe tener en cuenta los beneficios de este enfoque ya que los errores lógicos debido a un comportamiento extraño igualdad de objetos son dolorosas para depurar.

Me parece que es exactamente lo que usted quiere. Todo ese bloque se reduce a:

"si es la misma instancia exacta, devuelva cierto. Si son instancias independientes con los mismos valores de X e Y, de regreso cierto. Todos los demás casos (NULL, tipo diferente, diferentes valores x / y) devuelven falsa".

Su duda más código que me gustaría ¿Quieres escribir para un método equals. Hay una gran cantidad de controles redundantes tales como la comprobación de ReferenceEquals y hashcodes (sé que estos controles son redundantes debido a que las últimas líneas en su función comprueba la igualdad estructural). Centrarse en código que es simple y fácil de leer.

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;
}

Debido a que su método es igual utilizan la igualdad estructural, asegúrese de reemplazar GetHashCode con una implementación basada en sus campos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top