O compilador C # exige que sempre que um tipo personalizado defina operador ==
, ele também deve definir !=
(veja aqui ).
Por quê?
Estou curioso para saber por que os designers consideraram necessário e por que o compilador não pode usar como padrão uma implementação razoável para um dos operadores quando apenas o outro está presente. Por exemplo, Lua permite definir apenas o operador de igualdade e você obtém o outro gratuitamente. O C # pode fazer o mesmo solicitando que você defina == ou ambos == e! = E depois compile automaticamente o operador! = Ausente como !(left == right)
.
Entendo que existem casos de canto estranhos em que algumas entidades podem não ser iguais nem desiguais (como as NaN da IEEE-754), mas essas parecem ser a exceção, não a regra. Portanto, isso não explica por que os designers do compilador C # fizeram da exceção a regra.
Eu já vi casos de mão de obra deficiente em que o operador de igualdade é definido, então o operador de desigualdade é um copiar-colar com todas as comparações revertidas e todos os&& alternados para um || (você entendeu ... basicamente! (a == b) expandido pelas regras de De Morgan). Essa é uma prática ruim que o compilador poderia eliminar por design, como é o caso de Lua.
Nota: O mesmo vale para os operadores <> <=> =. Não consigo imaginar casos em que você precisará defini-los de maneiras não naturais. Lua permite definir apenas <e <= e define> = e> naturalmente através da negação dos formadores. Por que o C # não faz o mesmo (pelo menos 'por padrão')?
EDITAR
Aparentemente, existem razões válidas para permitir que o programador implemente verificações de igualdade e desigualdade da maneira que desejar. Algumas das respostas apontam para casos em que isso pode ser bom.
O núcleo da minha pergunta, no entanto, é por que isso é exigido à força no C # quando normalmente não é logicamente necessário?
Também está em contraste impressionante com as opções de design para interfaces .NET como Object.Equals
, IEquatable.Equals
IEqualityComparer.Equals
onde a falta de uma NotEquals
contrapartida mostra que a estrutura considera os !Equals()
objetos como desiguais e é isso. Além disso, classes Dictionary
e métodos como .Contains()
dependem exclusivamente das interfaces mencionadas acima e não usam os operadores diretamente, mesmo que sejam definidos. De fato, quando o ReSharper gera membros de igualdade, ele define ambos ==
e !=
em termos de, Equals()
e mesmo assim, somente se o usuário optar por gerar operadores. Os operadores de igualdade não são necessários pela estrutura para entender a igualdade de objetos.
Basicamente, a estrutura .NET não se preocupa com esses operadores, apenas se preocupa com alguns Equals
métodos. A decisão de exigir que os operadores == e! = Sejam definidos em conjunto pelo usuário está relacionada exclusivamente ao design da linguagem e não à semântica de objetos no que diz respeito ao .NET.