Es igual a más robusta aplicación para las clases personalizadas para la igualdad de valor en C #
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?
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.