Pergunta

Como é que o operador == funcionar realmente em C #? Se usado para comparar os objetos da classe A , vai tentar igualar todos A 's propriedades, ou vai procurar ponteiros para o mesmo local de memória (ou talvez outra coisa)?

Vamos criar um exemplo hipotético. Eu estou escrevendo um aplicativo que utiliza a API do Twitter, e tem um Tweet classe, que tem todas as propriedades de um único tweet: texto, remetente, data e hora, fonte, etc. Se eu quiser comparar objetos da classe Tweet de equivalência, eu só posso usar:

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

Will que verificação de equivalência de todas as propriedades do Tweet de classe entre a e b

Se não, seria a abordagem correta ser sobrecarregar o operador == para verificar explicitamente a equivalência de todos os campos?

UPDATE: A partir das duas primeiras respostas, estou certo em assumir:

  • Se o operador == ou Igual método não é sobrecarregado para uma classe, o operador == para o objeto classe é usada.
  • O operador == para os objeto cheques de classe para a igualdade no local de memória.
  • Eu tenho que sobrecarregar o operador == ou o Igual método para realizar esta tarefa.
  • Na sobrecarga, eu tenho que verificar se há equivalência nas propriedades manualmente, então não há nenhuma maneira de fazê-lo semi-automaticamente, digamos, em um loop , certo?

update # 2: Yuriy fez um comentário que é possível fazer verificação de equivalência em propriedades no operador == com reflexão . Como isso pode ser feito? Você poderia me dar algum código de exemplo? Obrigado!

Foi útil?

Solução

MSDN tem uma boa exemplo de como fazê-lo:

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

Então você sobrecarregar o == e =:

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

E não se esqueça de sobrecarregar o método GetHash.

Editar:

Eu escrevi o seguinte exemplo rápida para utilizar o reflexo em um comparar. Isso teria que ser muito mais abrangente, eu poderia tentar fazer um blog em que se as pessoas querem que eu:

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

Outras dicas

Para tipos de referência, as implementações padrão de tanto o operador == eo método Equals() simplesmente verificar se os dois objetos têm a mesma referência, e são, portanto, a mesma instância.

Se você quiser verificar o conteúdo de dois objetos diferentes são iguais, então você deve escrever o código para fazê-lo sozinho, de uma forma ou de outra. Seria possível fazer com reflexão (a MbUnit framework de teste faz algo nesse sentido), mas com um pesado penalidade de desempenho e uma boa chance de que ele não faria bem o que você espera de qualquer maneira, e você deve implementar == ou Equals e GetHashCode à mão.

A abordagem adequada é a sobrecarga do método da classe Tweet igual, além de o operador ==, como descrito aqui .

Will que cheque de equivalência de todas as propriedades da classe Tweet entre um e b?

Não

Se não, seria a abordagem correta ser sobrecarregar o operador == para verificar explicitamente a equivalência de todos os campos?

Você pode sobrecarregar o == do operador, ou sobrecarregar o Igual função.

Editar

@Yuriy deu um bom exemplo para compating todas as variáveis ??não públicos. Desde que eu também escreveu um exemplo, aqui está (o meu compara propriedades)

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

Você pode comparar as propriedades usando a reflexão:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top