c#编译器要求每当自定义类型定义操作符==
时,它也必须定义!=
(参见在这里)。
为什么?
我很好奇为什么设计人员认为这是必要的,为什么编译器不能默认为一个合理的实现操作符时,只有另一个存在。例如,Lua只允许定义相等操作符,而免费获得另一个。c#也可以做到这一点,要求你定义==或同时定义==和!=,然后自动将缺少的!=运算符编译为!(left == right)
。
我知道有一些奇怪的极端情况,一些实体可能既不相等也不相等(如IEEE-754 NaN),但这些似乎是例外,而不是规则。因此,这并不能解释为什么c#编译器设计人员将例外设置为规则。
我见过一些糟糕的情况,定义了相等运算符,然后不等式运算符是一个复制粘贴,每个比较都是反向的,每个&&换成||(你懂的…(a==b)通过德摩根法则展开)。这是编译器可以通过设计消除的不良实践,就像Lua一样。
< p >注意: 这同样适用于操作员<> <= >=。我无法想象在哪些情况下需要用非自然的方式来定义它们。Lua允许你只定义<和<=,通过前两者的否定自然地定义了>=和>。为什么c#不做同样的事情(至少在默认情况下)?< / p >编辑
显然,有充分的理由允许程序员根据自己的喜好执行相等和不相等的检查。一些答案指向了这样做可能不错的案例。
然而,我的问题的核心是,为什么在c#中强制要求通常而不是在逻辑上 ?
它也与。net接口的设计选择形成鲜明对比,如Object.Equals
, IEquatable.Equals
IEqualityComparer.Equals
,其中缺少NotEquals
对应对象表明框架认为!Equals()
对象是不平等的,就是这样。此外,像Dictionary
这样的类和像.Contains()
这样的方法只依赖于前面提到的接口,即使定义了操作符,也不直接使用操作符。事实上,当ReSharper生成相等成员时,它根据Equals()
定义了==
和!=
,即使这样,也只是在用户选择生成操作符时才这样做。框架不需要相等操作符来理解对象相等。
基本上,. net框架并不关心这些操作符,它只关心一些Equals
方法。要求用户同时定义==和!=操作符的决定纯粹与语言设计有关,而与. net关心的对象语义无关。