Share via


Diretrizes para substituição Equals() e operador == (guia de programação translation from VPE for Csharp)

No translation from VPE for Csharp, há dois tipos diferentes de igualdade: igualdade de referência e de igualdade do valor.Igualdade do valor é o significado normalmente compreendido de igualdade: Isso significa que dois objetos contiverem os mesmos valores.Por exemplo, dois inteiros com valor de 2 têm valor igualdade.Igualdade referência significa que há não dois objetos para comparar.Em vez disso, há duas referências de objeto e ambos se referir ao mesmo objeto.Isso pode ocorrer por meio da atribuição simples, sistema autônomo mostrado no exemplo a seguir:

System.Object a = new System.Object();
System.Object b = a;
System.Object.ReferenceEquals(a, b);  //returns true

Nesse código, existe apenas um objeto, mas há várias referências a esse objeto: a e b.Como ambos se referem ao mesmo objeto, eles têm referência igualdade.Se dois objetos têm igualdade de referência, eles também têm a igualdade do valor, mas igualdade do valor não garante a igualdade de referência.

Para verificar a igualdade de referência, use ReferenceEquals. Para verificar a igualdade do valor, use Equals.

Substituição Equals

Porque Equals é um método virtual, qualquer classe pode substituir a sua implementação. Qualquer classe que representa um valor, basicamente, qualquer tipo de valor, ou um conjunto de valores sistema autônomo um agrupar, sistema autônomo uma classe do número complexo, deverá substituir Equals. Se o tipo implementa IComparable, devem substituir Equals.

A nova implementação de Equals Siga todas as garantias de Equals:

  • x. Equals(x) retorna true.

  • x.Equals (y) retorna o mesmo valor sistema autônomo y. Equals (x).

  • if (x.Equals(y) e y. Equals (z)) retorna true e, em seguida, x. Equals (z) retorna true.

  • Chamadas sucessivas de x.Equals (y) retornam o valor mesmo enquanto sistema autônomo objetos referenciados pelo x e y não são modificadas.

  • x.Equals (nulo) retornará falso (para tipos de valor não nulo somente. Para obter mais informações, consulte Tipos anuláveis (guia de programação C#).)

A nova implementação de Equals não deve lançar exceções. Recomenda-se de que qualquer classe que sobrescreve Equals também substituir Object.GetHashCode. Também é recomendável que em adição a implementação de Equals (objeto), qualquer classe também implementar Equals (tipo) para seu próprio tipo, para melhorar o desempenho. Por exemplo:

class TwoDPoint : System.Object
{
    public readonly int x, y;

    public TwoDPoint(int x, int y)  //constructor
    {
        this.x = x;
        this.y = y;
    }

    public override bool Equals(System.Object obj)
    {
        // If parameter is null return false.
        if (obj == null)
        {
            return false;
        }

        // If parameter cannot be cast to Point return false.
        TwoDPoint p = obj as TwoDPoint;
        if ((System.Object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return (x == p.x) && (y == p.y);
    }

    public bool Equals(TwoDPoint p)
    {
        // If parameter is null return false:
        if ((object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return (x == p.x) && (y == p.y);
    }

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

Qualquer classe derivada pode chamar Equals na classe base deve fazê-lo antes de concluir a comparação. No exemplo a seguir, Equals chama a classe base Equals, que verifica se há um parâmetro nulo e compara o tipo do parâmetro com o tipo da classe derivada. Isso deixa a implementação de Equals na classe derivada da tarefa de verificar o novo campo de dados declarado na classe derivada:

class ThreeDPoint : TwoDPoint
{
    public readonly int z;

    public ThreeDPoint(int x, int y, int z)
        : base(x, y)
    {
        this.z = z;
    }

    public override bool Equals(System.Object obj)
    {
        // If parameter cannot be cast to ThreeDPoint return false:
        ThreeDPoint p = obj as ThreeDPoint;
        if ((object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return base.Equals(obj) && z == p.z;
    }

    public bool Equals(ThreeDPoint p)
    {
        // Return true if the fields match:
        return base.Equals((TwoDPoint)p) && z == p.z;
    }

    public override int GetHashCode()
    {
        return base.GetHashCode() ^ z;
    }
}

Substituir o operador ==

Por padrão, o operador == testes de referência de igualdade, determinando se as duas referências indicam o mesmo objeto. Portanto, tipos de referência não são necessário que implementar o operador == Para obter essa funcionalidade. Não quando um tipo é imutável, ou seja, sistema autônomo dados contidos na instância podem ser alterados, sobrecarga de operador == para comparar a igualdade do valor em vez da referência de igualdade pode ser útil porque, sistema autônomo objetos imutáveis, podem ser considerados sistema autônomo mesmos desde que eles tenham o mesmo valor. Não é uma mercadoria idéia substituir o operador == em tipos não imutáveis.

Operador sobrecarregado == implementações não devem lançar exceções. Qualquer tipo de operador que sobrecargas == também deverá sobrecarregar o operador !=. Por exemplo:

//add this code to class ThreeDPoint as defined previously
//
public static bool operator ==(ThreeDPoint a, ThreeDPoint b)
{
    // If both are null, or both are same instance, return true.
    if (System.Object.ReferenceEquals(a, b))
    {
        return true;
    }

    // If one is null, but not both, return false.
    if (((object)a == null) || ((object)b == null))
    {
        return false;
    }

    // Return true if the fields match:
    return a.x == b.x && a.y == b.y && a.z == b.z;
}

public static bool operator !=(ThreeDPoint a, ThreeDPoint b)
{
    return !(a == b);
}
Observação:

Um erro comum em sobrecargas de operador == é usar (a == b), (a == null), ou (b == null) Para verificar a igualdade de referência. Em vez disso, isso cria uma telefonar para o operador sobrecarregado ==, causando um loop infinito. Use ReferenceEquals ou converter o tipo de Object, para evitar o loop.

Consulte também

Conceitos

Guia de Programação C#

Referência

Instruções, expressões, e operadores (guia de programação C#)

Operadores (guia de programação translation from VPE for Csharp)

Operadores sobrecarregável (guia de programação translation from VPE for Csharp)

== Operador (translation from VPE for Csharp Reference)

Operador () (translation from VPE for Csharp Reference)