Como posso verificar para valores nulos em uma '==' a sobrecarga do operador sem recursão infinita?

StackOverflow https://stackoverflow.com/questions/73713

  •  09-06-2019
  •  | 
  •  

Pergunta

A seguir fará com que a recursividade infinita sobre o operador == de sobrecarga do método

    Foo foo1 = null;
    Foo foo2 = new Foo();
    Assert.IsFalse(foo1 == foo2);

    public static bool operator ==(Foo foo1, Foo foo2) {
        if (foo1 == null) return foo2 == null;
        return foo1.Equals(foo2);
    }

Como posso verificar nulos?

Foi útil?

Solução

Utilização ReferenceEquals:

Foo foo1 = null;
Foo foo2 = new Foo();
Assert.IsFalse(foo1 == foo2);

public static bool operator ==(Foo foo1, Foo foo2) {
    if (object.ReferenceEquals(null, foo1))
        return object.ReferenceEquals(null, foo2);
    return foo1.Equals(foo2);
}

Outras dicas

O elenco objeto no método de sobrecarga:

public static bool operator ==(Foo foo1, Foo foo2) {
    if ((object) foo1 == null) return (object) foo2 == null;
    return foo1.Equals(foo2);
}

Utilização ReferenceEquals.Do Fóruns do MSDN:

public static bool operator ==(Foo foo1, Foo foo2) {
    if (ReferenceEquals(foo1, null)) return ReferenceEquals(foo2, null);
    if (ReferenceEquals(foo2, null)) return false;
    return foo1.field1 == foo2.field2;
}

Tente Object.ReferenceEquals(foo1, null)

De qualquer maneira, eu não recomendaria a sobrecarga do ==operador;ele deve ser usado para a comparação de referências, e usar Equals para a "semântica" comparações.

Se eu tiver overrided bool Equals(object obj) e eu quero que o operador == e Foo.Equals(object obj) para retornar a mesma resposta, eu geralmente implementar o != operador de como este:

public static bool operator ==(Foo foo1, Foo foo2) {
  return object.Equals(foo1, foo2);
}
public static bool operator !=(Foo foo1, Foo foo2) {
  return !object.Equals(foo1, foo2);
}

O operador == irá, em seguida, depois de fazer todos os cheques nulos para mim acabam chamando foo1.Equals(foo2) que eu assumi para fazer o verifique se os dois são iguais.

Se você estiver usando C# 7 ou mais tarde, você pode usar a constante nulo correspondência de padrão:

public static bool operator==(Foo foo1, Foo foo2)
{
    if (foo1 is null)
        return foo2 is null;
    return foo1.Equals(foo2);
}

Isso dá a você um pouco mais puro do código do que o objecto de chamada.ReferenceEquals(foo1, null)

Minha abordagem é a de fazer

(object)item == null

sobre o que eu estou confiando em object'do próprio operador de igualdade que não pode dar errado.Ou uma extensão personalizada método (e uma sobrecarga):

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null;
}

public static bool IsNull<T>(this T? obj) where T : struct
{
    return !obj.HasValue;
}

ou para lidar com mais casos, pode ser:

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null || obj == DBNull.Value;
}

A restrição impede IsNull em tipos de valor.Agora a sua doce como chamar

object obj = new object();
Guid? guid = null; 
bool b = obj.IsNull(); // false
b = guid.IsNull(); // true
2.IsNull(); // error

o que significa que eu tenho um consistente/não-passível de erro estilo de verificar nulos todo.Eu também tenho encontrado (object)item == null é muito, muito, muito ligeiramente mais rápido do que Object.ReferenceEquals(item, null), mas só se importa (atualmente estou trabalhando em algo que eu mandei para micro-otimizar tudo!).

Para ver um guia completo sobre a implementação da igualdade verificações, consulte O que é a "Melhor Prática" Para a Comparação de Duas Instâncias de um Tipo de Referência?

Estática Equals(Object, Object) método indica se dois objetos, objA e objB, são iguais.Ele também permite que você teste os objectos cujo valor é null para a igualdade.Ele compara objA e objB para a igualdade da seguinte maneira:

  • Ele determina se os dois objectos que representam o mesmo objeto de referência.Se o fizerem, o método retorna true.Este teste é equivalente a chamar a ReferenceEquals o método.Além disso, se ambos os objA e objB são null, o método retorna true.
  • Ele determina se quer objA ou objB é null.Se assim for, ele retorna false.Se os dois objectos não representam o mesmo objeto de referência e nem é null, ele chama objA.Equals(objB) e retorna o resultado.Isso significa que, se objA substitui a Object.Equals(Object) método, esta substituição é chamado.

.

public static bool operator ==(Foo objA, Foo objB) {
    return Object.Equals(objA, objB);
}

respondendo mais substituindo o operador como para comparar null que redireciona aqui como uma duplicata.

Nos casos em que isso está sendo feito para suportar Objectos de Valor, acho que a nova notação para a calhar, e gostaria de garantir que só existe um lugar onde a comparação é feita.Também aproveitando o Objeto.É igual a(A, B) simplifica o nulo verifica.

Isto irá sobrecarregar ==, !=, É igual a, e GetHashCode

    public static bool operator !=(ValueObject self, ValueObject other) => !Equals(self, other);
    public static bool operator ==(ValueObject self, ValueObject other) => Equals(self, other);
    public override bool Equals(object other) => Equals(other as ValueObject );
    public bool Equals(ValueObject other) {
        return !(other is null) && 
               // Value comparisons
               _value == other._value;
    }
    public override int GetHashCode() => _value.GetHashCode();

Para mais complicado objetos de adicionar outras comparações em pares e uma rica GetHashCode.

Há, na verdade, uma forma mais simples de verificar contra null neste caso:

if (foo is null)

Que é isso!

Esta funcionalidade foi introduzida no C# 7

Um erro comum na sobrecarga do operador == é para usar (a == b), (a ==null), ou (b == null) para verificar igualdade de referência.Este, em vez resultados uma chamada para o operador sobrecarregado ==, causando um infinite loop.Utilização ReferenceEquals o elenco do tipo de Objeto, para evitar o loop.

confira este

// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))// using ReferenceEquals
{
    return true;
}

// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))// using casting the type to Object
{
    return false;
}

referência Diretrizes para a Sobrecarga é Igual a() e o Operador ==

Você pode tentar usar uma propriedade de objeto e pegar a resultante de NullReferenceException.Se a propriedade tentar é herdada ou substituído, de Objecto e, em seguida, isso funciona para qualquer classe.

public static bool operator ==(Foo foo1, Foo foo2)
{
    //  check if the left parameter is null
    bool LeftNull = false;
    try { Type temp = a_left.GetType(); }
    catch { LeftNull = true; }

    //  check if the right parameter is null
    bool RightNull = false;
    try { Type temp = a_right.GetType(); }
    catch { RightNull = true; }

    //  null checking results
    if (LeftNull && RightNull) return true;
    else if (LeftNull || RightNull) return false;
    else return foo1.field1 == foo2.field2;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top