ti-enxame.com

Comparando duas instâncias de uma classe

Eu tenho uma classe como essa

public class TestData
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }   
}

Quero saber se é possível comparar diretamente as instâncias dessa classe e descobrir que são exatamente iguais? qual é o mecanismo? Estou procurando algo parecido com if(testData1 == testData2) //Do Something E se não, como fazer isso?

11
Saeid Yazdani

Você deve implementar o IEquatable<T> na sua classe, o que permitirá que você defina sua lógica de igualdade. Na verdade, você deve substituir o método Equals também.

public class TestData : IEquatable<TestData>
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }   

  // Overriding Equals member method, which will call the IEquatable implementation
  // if appropriate.

   public override bool Equals( Object obj )
   {
       var other = obj as TestData;
       if( other == null ) return false;

       return Equals (other);             
   }

   public override int GetHashCode()
   {
      // Provide own implementation
   }


   // This is the method that must be implemented to conform to the 
   // IEquatable contract

   public bool Equals( TestData other )
   {
       if( other == null )
       {
            return false;
       }

       if( ReferenceEquals (this, other) )
       {
            return true;
       }

       // You can also use a specific StringComparer instead of EqualityComparer<string>
       // Check out the specific implementations (StringComparer.CurrentCulture, e.a.).
       if( EqualityComparer<string>.Default.Compare (Name, other.Name) == false )
       {
           return false;
       }
       ...

       // To compare the members array, you could perhaps use the 
       // [SequenceEquals][2] method.  But, be aware that [] {"a", "b"} will not
       // be considerd equal as [] {"b", "a"}

       return true;

   }

}
20
Frederik Gheysels

Existem três maneiras pelas quais objetos de algum tipo de referência T podem ser comparados entre si:

  1. Com o object.Equals método
  2. Com uma implementação de IEquatable<T>.Equals (apenas para tipos que implementam IEquatable<T>)
  3. Com o operador de comparação ==

Além disso, existem duas possibilidades para cada um desses casos:

  1. O tipo estático dos objetos que estão sendo comparados é T (ou alguma outra base de T)
  2. O tipo estático dos objetos que estão sendo comparados é object

As regras que você absolutamente precisa saber são:

  • O padrão para Equals e operator== é testar a igualdade de referência
  • As implementações de Equals funcionarão corretamente, independentemente do tipo estático dos objetos que estão sendo comparados.
  • IEquatable<T>.Equals deve sempre se comportar da mesma maneira que object.Equals, mas se o tipo estático dos objetos for T, ele oferecerá um desempenho um pouco melhor

Então, o que tudo isso significa na prática?

Como regra geral, você deve usar Equals para verificar a igualdade (substituindo object.Equals conforme necessário) e implemente IEquatable<T> também para fornecer um desempenho um pouco melhor. Nesse caso object.Equals deve ser implementado em termos de IEquatable<T>.Equals.

Para alguns tipos específicos (como System.String) também é aceitável usar operator==, embora você tenha cuidado para não fazer "comparações polimórficas". Os métodos Equals, por outro lado, funcionarão corretamente, mesmo se você fizer essas comparações.

Você pode ver um exemplo de comparação polimórfica e por que isso pode ser um problema aqui .

Por fim, nunca esqueça que se você substituir object.Equals você também deve substituir object.GetHashCode adequadamente.

6
Jon

Uma maneira de fazer isso é implementar IEquatable<T>

public class TestData : IEquatable<TestData>
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }

   public bool Equals(TestData other)
   {
        if (this.Name != other.Name) return false;
        if (this.type != other.type) return false;

        // TODO: Compare Members and return false if not the same

        return true;
   }
}


if (testData1.Equals(testData2))
    // classes are the same

Você também pode simplesmente substituir o método Equals (objeto) (de System.Object); se fizer isso, também deverá substituir GetHashCode veja aqui

5
Patrick McDonald

Antes de tudo, é difícil definir igualdade e somente você pode definir o que significa igualdade para você.

  1. Isso significa que os membros têm o mesmo valor
  2. Ou eles estão apontando para o mesmo local.

Aqui está uma discussão e uma resposta aqui

O que é "Prática recomendada" para comparar duas instâncias de um tipo de referência?

1
user182630

Vejo muitas boas respostas aqui, mas caso você queira que a comparação funcione como

if(testData1 == testData2) // DoSomething

em vez de usar a função Equals, você pode substituir os operadores == e! =:

public static bool operator == (TestData left, TestData right)
{
    bool comparison = true; //Make the desired comparison
    return comparison;
}

public static bool operator != (TestData left, TestData right)
{
    return !(left == right);
}
1
roozbeh S

Você pode substituir o método equals e, dentro dele, comparar manualmente os objetos

Também dê uma olhada em Diretrizes para sobrecarga de iguais () e operador ==

1
Haris Hasan

Você precisará definir as regras que tornam o objeto A igual ao objeto B e substituir o operador Equals para esse tipo.

http://msdn.Microsoft.com/en-us/library/ms173147 (v = vs.80) .aspx

1
DaveRead

Implemente o IEquatable<T> interface. Isso define um método generalizado que um tipo ou classe de valor implementa para criar um método específico de tipo para determinar a igualdade de instâncias. Mais informações aqui:

http://msdn.Microsoft.com/en-us/library/ms131187.aspx

1
Enigma State