O seguinte causará recursão infinita no método de sobrecarga do operador ==
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 faço para verificar se há nulos?
c#
.net
operator-overloading
Andrew Jones
fonte
fonte
Assert.IsFalse(foo2 == foo1);
foo1.Equals(foo2)
significa se, por exemplo, eu querofoo1 == foo2
apenas sefoo1.x == foo2.x && foo1.y == foo2.y
? Não é esta resposta ignorando o caso ondefoo1 != null
masfoo2 == null
?if (foo1 is null) return foo2 is null;
Cast para objeto no método de sobrecarga:
fonte
(object)foo1 == null
oufoo1 == (object)null
irão para a sobrecarga embutida==(object, object)
e não para a sobrecarga definida pelo usuário==(Foo, Foo)
. É como a resolução de sobrecarga nos métodos.Use
ReferenceEquals
. Dos fóruns do MSDN :fonte
Experimentar
Object.ReferenceEquals(foo1, null)
De qualquer forma, não recomendo sobrecarregar a
==
operadora; deve ser usado para comparar referências eEquals
para comparações "semânticas".fonte
Se eu tiver substituído
bool Equals(object obj)
e eu quero que o operador==
eFoo.Equals(object obj)
para retornar o mesmo valor, eu costumo implementar o!=
operador como este:O operador
==
, então, após fazer todas as verificações de nulos para mim, acabará chamando ofoo1.Equals(foo2)
que eu substituí para fazer a verificação real se os dois são iguais.fonte
Object.Equals(Object, Object)
lado a ladoObject.ReferenceEquals(Object, Object)
, é bastante claro queObject.Equals(Object, Object)
faz tudo conforme sugerido nas outras respostas fora da caixa. Por que não usar?==
operador se tudo o que você deseja é o comportamento padrão. Você só deve sobrecarregar quando precisar implementar lógica de comparação personalizada, ou seja, algo mais do que uma verificação de igualdade de referência.==
é desejável (a questão implica isso), estou simplesmente apoiando esta resposta, sugerindo queObject.Equals(Object, Object)
tornaReferenceEquals
desnecessários outros truques, como o uso ou conversão explícita (portanto, "por que não usar?", "isso" sendoEquals(Object, Object)
). Mesmo que não relacionado, seu ponto também está correto, e eu iria além: apenas sobrecarga==
para objetos que podemos classificar como "objetos de valor".Object.Equals(Object, Object)
por sua vez, chama Object.Equals (Object), que é um método virtual que Foo provavelmente substitui. O fato de você ter introduzido uma chamada virtual em sua verificação de igualdade pode afetar a capacidade do compilador de otimizar (por exemplo, em linha) essas chamadas. Isso provavelmente é insignificante para a maioria dos propósitos, mas em certos casos um pequeno custo em um operador de igualdade pode significar um custo enorme para loops ou estruturas de dados ordenadas.Se você estiver usando C # 7 ou posterior, poderá usar correspondência de padrão constante nula:
Isso fornece um código um pouco mais limpo do que o objeto de chamada.ReferenceEquals (foo1, null)
fonte
public static bool operator==( Foo foo1, Foo foo2 ) => foo1?.Equals( foo2 ) ?? foo2 is null;
Na verdade, há uma maneira mais simples de verificar
null
neste caso:É isso aí!
Este recurso foi introduzido no C # 7
fonte
Minha abordagem é fazer
no qual estou contando com
object
o próprio operador de igualdade, que não pode dar errado. Ou um método de extensão personalizada (e uma sobrecarga):ou para lidar com mais casos, podem ser:
A restrição impede
IsNull
tipos de valor. Agora é tão doce quanto chamaro que significa que sempre tenho um estilo consistente / não sujeito a erros de verificação de nulos. Eu também descobri que
(object)item == null
é muito, muito ligeiramente mais rápido do queObject.ReferenceEquals(item, null)
, mas apenas se for importante (atualmente estou trabalhando em algo onde devo micro-otimizar tudo!).Para ver um guia completo sobre a implementação de verificações de igualdade, consulte O que é "prática recomendada" para comparar duas instâncias de um tipo de referência?
fonte
DbNull
, IMO - os casos em que isso não geraria problemas relacionados ao SRP são muito raros. Apenas apontar o cheiro do código, porém, pode muito bem ser apropriado.O
Equals(Object, Object)
método estático indica se dois objetos,objA
eobjB
, são iguais. Ele também permite que você teste objetos cujo valor énull
para igualdade. Ele comparaobjA
eobjB
para igualdade da seguinte forma:true
. Este teste é equivalente a chamar oReferenceEquals
método. Além disso, seobjA
eobjB
foremnull
, o método retornatrue
.objA
ouobjB
énull
. Nesse caso, ele retornafalse
. Se os dois objetos não representam a mesma referência de objeto e nenhum énull
, ele chamaobjA.Equals(objB)
e retorna o resultado. Isso significa que, seobjA
substituir oObject.Equals(Object)
método, essa substituição será chamada..
fonte
respondendo mais ao operador de substituição como comparar com nulo que redireciona aqui como uma duplicata.
Nos casos em que isso está sendo feito para oferecer suporte a Objetos de Valor, considero a nova notação muito útil e gosto de garantir que haja apenas um lugar onde a comparação é feita. Também aproveitar Object.Equals (A, B) simplifica as verificações de nulos.
Isso sobrecarregará ==,! =, Equals e GetHashCode
Para objetos mais complicados, adicione comparações adicionais em Equals e um GetHashCode mais rico.
fonte
Para uma sintaxe moderna e condensada:
fonte
Veja isso
Diretrizes de referência para Sobrecarga Equals () e Operador ==
fonte
Você pode tentar usar uma propriedade de objeto e capturar a NullReferenceException resultante. Se a propriedade que você tentar for herdada ou substituída de Object, isso funcionará para qualquer classe.
fonte