Pregunta

¿Cómo funciona realmente el operador == en C #? Si solía comparar objetos de la clase A , ¿intentará hacer coincidir todas las propiedades de A o buscará punteros en la misma ubicación de memoria (o tal vez algo más)?

Creemos un ejemplo hipotético. Estoy escribiendo una aplicación que utiliza la API de Twitter, y tiene una clase Tweet , que tiene todas las propiedades de un solo tweet: texto, remitente, fecha y hora, fuente, etc. Si yo quiero comparar objetos de clase Tweet para equivalencia, ¿puedo usar:

Tweet a, b;
if (a == b)
{
//do something...
}

¿Comprobará la equivalencia de todas las propiedades de la clase Tweet entre a y b ?

Si no, ¿sería el enfoque correcto sobrecargar el operador == para verificar explícitamente la equivalencia de todos los campos?

ACTUALIZACIÓN: De las dos primeras respuestas, estoy en lo cierto al suponer:

  • Si el operador == o el método Equals no está sobrecargado para una clase, el operador == para el objeto se usa la clase.
  • El operador == para la clase objeto comprueba la igualdad en la ubicación de la memoria.
  • Tengo que sobrecargar el operador == o el método Equals para realizar esta tarea.
  • En la sobrecarga, tengo que verificar la equivalencia en las propiedades manualmente, por lo que no hay forma de hacerlo de forma semiautomática, digamos, en un bucle , ¿verdad?

ACTUALIZACIÓN # 2: Yuriy hizo un comentario de que es posible verificar la equivalencia en las propiedades en el operador == con reflexión . ¿Cómo se puede hacer esto? ¿Me podría dar un código de muestra? Gracias!

¿Fue útil?

Solución

MSDN tiene un buen ejemplo de cómo hacerlo:

   public override bool Equals(object o) 
   {
      try 
      {
         return (bool) (this == (DBBool) o);
      }
      catch 
      {
         return false;
      }
   }

Entonces sobrecargas el == y! =:

// Equality operator. Returns dbNull if either operand is dbNull, 
   // otherwise returns dbTrue or dbFalse:
   public static DBBool operator ==(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value == y.value? dbTrue: dbFalse;
   }

   // Inequality operator. Returns dbNull if either operand is
   // dbNull, otherwise returns dbTrue or dbFalse:
   public static DBBool operator !=(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value != y.value? dbTrue: dbFalse;
   }

Y no olvides sobrecargar el método GetHash.

Editar:

Escribí la siguiente muestra rápida para usar la reflexión en una comparación. Esto tendría que ser mucho más completo, podría intentar hacer un blog si la gente quiere que:

public class TestEquals
{
    private int _x;
    public TestEquals(int x)
    {
        this._x = x;
    }

    public override bool Equals(object obj)
    {
        TestEquals te = (TestEquals)obj;
        if (te == null) return false;

        foreach (var field in typeof(TestEquals)
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (!field.GetValue(this).Equals(field.GetValue(te)))
                return false;
        }
        return true;
    }
}

Otros consejos

Para los tipos de referencia, las implementaciones predeterminadas tanto del operador == como del método Equals () simplemente verificarán que ambos objetos tengan la misma referencia, y por lo tanto la misma instancia.

Si desea verificar que los contenidos de dos objetos diferentes son iguales, debe escribir el código para hacerlo usted mismo, de una forma u otra. Sería posible hacer con la reflexión (el MbUnit prueba marco hace algo en este sentido) pero con penalización de rendimiento y una buena posibilidad de que no haga lo que esperaba de todos modos, y debe implementar == o Equals y GetHashCode por mano.

El enfoque adecuado es la sobrecarga del método de igualdad de la clase Tweet además del operador ==, como se describe aquí .

  

¿Verificará eso la equivalencia de todas las propiedades de la clase Tweet entre a y b?

No

  

Si no, ¿sería el enfoque correcto sobrecargar el operador == para verificar explícitamente la equivalencia de todos los campos?

Puede sobrecargar el operador == o sobrecargar la función Equals .

Editar

@Yuriy dio un buen ejemplo para comparar todas las variables no públicas. Como también escribí un ejemplo, aquí está (el mío compara propiedades)

class TwitterItem
{
    private string myValue = "default value";
    public string Value1
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value2
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value3
    {
        get { return myValue; }
        set { myValue = value; }
    }

    public override bool Equals(object obj)
    {
        if (base.Equals(obj)) return true;

        Type type = typeof(TwitterItem);
        PropertyInfo[] properties = type.GetProperties();

        foreach (PropertyInfo property in properties)
        {
            if (false == property.GetValue(this, null).Equals(property.GetValue(obj, null)))
                return false;
        }

        return true;
    }
}

Puede comparar las propiedades usando la reflexión:

var a = new Entity() { Name = "test", ID = "1" };
var b = new Entity() { Name = "test", ID = "1" };
var c = new Entity() { Name = "test", ID = "2" };
System.Diagnostics.Debug.WriteLine(a.Equals(b));//Returns true
System.Diagnostics.Debug.WriteLine(a.Equals(c));//Returns false


public class Entity
{
    public string Name { get; set; }
    public string ID { get; set; }
    public override bool Equals(object obj)
    {
        var t = obj.GetType();
        foreach (var p in t.GetProperties())
        {
            if (t.GetProperty(p.Name).GetValue(obj, null) != t.GetProperty(p.Name).GetValue(this, null))
                return false;
        }
        return true;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top