Implementing the Equals Method

Para obter informações sobre como implementar o operador de igualdade (= =), consulte diretrizes para o operador de igualdade (= =) e a implementação é igual a.

  • Substituir o GetHashCode método para permitir que um tipo de funcionar corretamente em uma tabela de hash.

  • Não jogue uma exceção na implementação de um é igual a método. Em vez disso, retornar false para um argumento nulo.

  • Siga o contract definido na O método de Object. Equals da seguinte maneira:

    • x.Equals(x)Retorna true.

    • x.Equals(y)Retorna o mesmo valor de y.Equals(x).

    • (x.Equals(y) && y.Equals(z))Retorna true se x.Equals(z) retorna true.

    • Invocações sucessivas de x.Equals(y) retornar o mesmo valor, como os objetos referenciados por x e y não são modificados.

    • x.Equals(null)Retorna false.

  • Para alguns tipos de objetos, é desejável que é igual a testar igualdade de valor em vez de igualdade referencial. Tais implementações de é igual a retornar true se os dois objetos terá o mesmo valor, mesmo que não estejam na mesma instância. A definição do que constitui o valor de um objeto é o implementador do tipo, mas é normalmente alguns ou todos os dados armazenados em variáveis de instância do objeto. Por exemplo, o valor de uma seqüência de caracteres é baseado nos caracteres da seqüência de caracteres; o é igual a método o seqüência classe retorna true para quaisquer duas instâncias de uma seqüência de caracteres que contêm os mesmos caracteres na mesma ordem.

  • Quando o é igual a método de uma classe base fornece a igualdade do valor, uma substituição do é igual a em uma classe derivada deve chamar a implementação herdada do é igual a.

  • Se você está programando em um idioma que ofereça suporte a sobrecarga de operador e escolha para sobrecarregar o operador de igualdade (= =) para um tipo especificado, o que o tipo deve substituir o é igual a método. Tais implementações do é igual a método deve retornar os mesmos resultados que o operador de igualdade. Essa diretriz a seguir ajudará a garantir que código de biblioteca de classe usando é igual a (como ArrayList e Hashtable) funciona de maneira que seja consistente com a maneira como o operador de igualdade é usado pelo código do aplicativo.

  • Se você estiver implementando um tipo de valor, você deve considerar a substituição de é igual a método para obter um desempenho maior sobre a implementação padrão do é igual a método em ValueType. Se você substituir é igual a e o idioma oferece suporte a sobrecarga de operador, você deverá sobrecarregar o operador de igualdade para o tipo de valor.

  • Se você estiver implementando os tipos de referência, você deve considerar a substituição de é igual a método em um tipo de referência, se o seu tipo se parece com um tipo de base, como Point, String, BigNumbere assim por diante. A maioria dos tipos de referência não deverá sobrecarregar o operador de igualdade, mesmo se elas substituirão é igual a. No entanto, se você estiver implementando um tipo de referência destina-se ter a semântica de valor, como, por exemplo, um tipo de número complexo, você deve substituir o operador de igualdade.

  • Se você implementar a IComparable interface de um determinado tipo, você deve substituir é igual a nesse tipo.

Exemplos

Os exemplos de código a seguir demonstram a implementação, substituindo chamando e sobrecarga de é igual a método.

Implementing the Equals Method

O exemplo de código a seguir contém duas chamadas para a implementação padrão de é igual a método.

Imports System
Class SampleClass   
   Public Shared Sub Main()
      Dim obj1 As New System.Object()
      Dim obj2 As New System.Object()
      Console.WriteLine(obj1.Equals(obj2))
      obj1 = obj2
      Console.WriteLine(obj1.Equals(obj2))
   End Sub
End Class
using System;
class SampleClass 
{
   public static void Main() 
   {
      Object obj1 = new Object();
      Object obj2 = new Object();
      Console.WriteLine(obj1.Equals(obj2));
      obj1 = obj2; 
      Console.WriteLine(obj1.Equals(obj2)); 
   }
}

A saída do código anterior é o seguinte:

False
True

Substituindo o método Equals

O seguinte código exemplo mostra um Point classe substitui o é igual a método para fornecer a igualdade do valor e uma classe Point3D, que é derivada de Point. Porque o Point a substituição da classe do é igual a é o primeiro na cadeia de herança para apresentar a igualdade do valor, o é igual a método da classe base (que é herdada da objeto e verificações de igualdade referencial) não é invocado. No entanto, Point3D.Equals chama Point.Equals porque Point implementa é igual a de maneira que fornece a igualdade do valor.

Namespace Examples.DesignGuidelines.EqualsImplementation

Public Class Point  
   Protected x As Integer
   Protected y As Integer

   Public Sub New (xValue As Integer, yValue As Integer)
    Me.x = xValue
    Me.y = yValue
   End Sub

   Public Overrides Overloads Function Equals(obj As Object) As Boolean

      If obj Is Nothing OrElse Not Me.GetType() Is obj.GetType() Then
         Return False
      End If

      Dim p As Point = CType(obj, Point)
      Return Me.x = p.x And Me.y = p.y
   End Function 

   Public Overrides Function GetHashCode() As Integer
      Return x Xor y
   End Function 
End Class 

Public Class Point3D
   Inherits Point
   Private z As Integer

   Public Sub New (xValue As Integer, yValue As Integer, zValue As Integer)
      MyBase.New(xValue, yValue)
      Me.z = zValue
   End Sub

   Public Overrides Overloads Function Equals(obj As Object) As Boolean
      Return MyBase.Equals(obj) And z = CType(obj, Point3D).z
   End Function 

   Public Overrides Function GetHashCode() As Integer
      Return MyBase.GetHashCode() Xor z
   End Function 
End Class 

End Namespace

using System;

namespace Examples.DesignGuidelines.EqualsImplementation
{
class Point: object 
{
   protected int x, y;

   public Point(int xValue, int yValue)
   {
        x = xValue;
        y = yValue;
   }
   public override bool Equals(Object obj) 
   {
      // Check for null values and compare run-time types.
      if (obj == null || GetType() != obj.GetType()) 
         return false;

      Point p = (Point)obj;
      return (x == p.x) && (y == p.y);
   }
   public override int GetHashCode() 
   {
      return x ^ y;
   }
}

class Point3D: Point 
{
   int z;

   public Point3D(int xValue, int yValue, int zValue) : base(xValue, yValue)
   {
        z = zValue;
   }
   public override bool Equals(Object obj) 
   {
      return base.Equals(obj) && z == ((Point3D)obj).z;
   }
   public override int GetHashCode() 
   {
      return base.GetHashCode() ^ z;
   }
}
}
using namespace System;

namespace Examples { namespace DesignGuidelines { namespace EqualsImplementation
{
    ref class Point : Object
    {
    protected:
        int x, y;

    public:
        Point(int xValue, int yValue)
        {
            x = xValue;
            y = yValue;
        }

        virtual bool Equals(Object^ obj) override
        {
            // Check for null values and compare run-time types.
            if (obj == nullptr || GetType() != obj->GetType())
            {
                return false;
            }

            Point^ p = (Point^)obj;

            return (x == p->x) && (y == p->y);
       }

       virtual int GetHashCode() override
       {
           return x ^ y;
       }
    };

    ref class Point3D : Point
    {
    private:
        int z;

    public:
        Point3D(int xValue, int yValue, int zValue) : Point(xValue, yValue)
        {
            z = zValue;
        }

        virtual bool Equals(Object^ obj) override
        {
            return Point::Equals(obj) && z == ((Point3D^)obj)->z;
        }

        virtual int GetHashCode() override
        {
            return Point::GetHashCode() ^ z;
        }
    };
}}}

O Point.Equals método verifica que o obj argumento não for null, e ele faz referência a uma instância do mesmo tipo de objeto. Se qualquer uma das verificações falhar, o método retorna false. O é igual a método usa o GetType método para determinar se os tipos de tempo de execução dos dois objetos são idênticos. Observe que typeof (TypeOf em Visual Basic) não é usado aqui porque ela retorna o tipo estático. Se o método tivesse usado uma verificação do formulário obj is Point em vez disso, a verificação retornaria true em casos onde obj é uma instância de uma classe derivada de Point, mesmo que obj e a instância atual não são do mesmo tipo de tempo de execução. Tendo verificado que ambos os objetos são do mesmo tipo, os método de projeções obj digitar Point e retorna o resultado de comparar as variáveis de instância de dois objetos.

Em Point3D.Equals, o herdadas é igual a método é chamado antes que qualquer outra coisa seja feita. O herdadas é igual a método verifica se obj não é null, que obj é uma instância da mesma classe de objeto e as variáveis de instância herdadas correspondentes. Somente quando o herdadas é igual a retorna true oferece o método compare as variáveis de instância introduzidas na classe derivada. Especificamente, a projeção para Point3D não é executado, a menos que obj foi determinado ser do tipo Point3D ou uma classe derivada de Point3D.

Usando o método Equals para comparar as variáveis de instância

No exemplo anterior, o operador de igualdade (= =) é usado para comparar as variáveis de instância individual. Em alguns casos, é apropriado usar o é igual a método para comparar as variáveis de instância em um é igual a implementação, conforme mostrado no exemplo de código a seguir.

Imports System

Class Rectangle
   Private a, b As Point
   
   Public Overrides Overloads Function Equals(obj As [Object]) As Boolean
      If obj Is Nothing Or Not Me.GetType() Is obj.GetType() Then
         Return False
      End If
      Dim r As Rectangle = CType(obj, Rectangle)
      ' Use Equals to compare instance variables.
      Return Me.a.Equals(r.a) And Me.b.Equals(r.b)
   End Function 
   
   Public Overrides Function GetHashCode() As Integer
      Return a.GetHashCode() ^ b.GetHashCode()
   End Function 
End Class 
using System;
class Rectangle 
{
   Point a, b;
   public override bool Equals(Object obj) 
   {
      if (obj == null || GetType() != obj.GetType()) return false;
      Rectangle r = (Rectangle)obj;
      // Use Equals to compare instance variables.
      return a.Equals(r.a) && b.Equals(r.b);
   }
   public override int GetHashCode() 
   {
      return a.GetHashCode() ^ b.GetHashCode();
   }
}

Sobrecarga de operador de igualdade (= =) e o método Equals

Em algumas linguagens de programação, como, por exemplo, C#, sobrecarga de operador é suportado. Quando um tipo sobrecarrega o operador de igualdade (= =), também deverá substituir o é igual a método para fornecer a mesma funcionalidade. Normalmente, isso é feito escrevendo o é igual a método em termos do operador sobrecarregado de igualdade (= =), como no exemplo de código a seguir.

public struct Complex 
{
   double re, im;
   public override bool Equals(Object obj) 
   {
      return obj is Complex && this == (Complex)obj;
   }
   public override int GetHashCode() 
   {
      return re.GetHashCode() ^ im.GetHashCode();
   }
   public static bool operator ==(Complex x, Complex y) 
   {
      return x.re == y.re && x.im == y.im;
   }
   public static bool operator !=(Complex x, Complex y) 
   {
      return !(x == y);
   }
}

Porque Complex é C# struct (um tipo de valor), ele é conhecido que nenhuma classe será derivado Complex. Portanto, o é igual a método não precisa comparar o GetType resultados para cada objeto. Em vez disso, ele usa o é operador para verificar o tipo da obj parâmetro.

Portions Copyright 2005 Microsoft Corporation. Todos os direitos reservados.

Portions Copyright Addison-Wesley Corporation. Todos os direitos reservados.

Para obter mais informações sobre as diretrizes de design, consulte a "diretrizes de Design do Framework: Convenções, idiomas e padrões de reutilizável.Bibliotecas de rede" catálogo por Krzysztof Cwalina e Brad Abrams, publicado pela Addison-Wesley, 2005.

Consulte também

Outros recursos

Diretrizes de Design para desenvolvimento bibliotecas de classe