C# Object.Equals的奇怪实现

C# Object.Equals的奇怪实现,c#,C#,我在看报纸。在评论部分提到: 如果两个对象不代表相同的对象引用,则 两者都不为null,它调用objA.Equals(objB)并返回结果。 这意味着如果objA重写Object.Equals(Object)方法, 这种覆盖称为 我的问题是,为什么他们没有将这一部分实现为objA.Equals(objB)&&objB.Equals(objA),以使等式对称,并仅在关系的一侧关联?调用object.Equals时,它可能会导致奇怪的行为 编辑:当objA类型重写Equals方法并将其作为不可预测的

我在看报纸。在评论部分提到:

如果两个对象不代表相同的对象引用,则 两者都不为null,它调用objA.Equals(objB)并返回结果。 这意味着如果objA重写Object.Equals(Object)方法, 这种覆盖称为

我的问题是,为什么他们没有将这一部分实现为
objA.Equals(objB)&&objB.Equals(objA)
,以使等式对称,并仅在关系的一侧关联?调用
object.Equals
时,它可能会导致奇怪的行为


编辑:当objA类型重写
Equals
方法并将其作为不可预测的内容实现时,可能会发生奇怪的行为,但objB类型不会重写
Equals
基本上,这只对有缺陷的
Equals
实现的开发人员有用。从:

对于
Equals(Object)
方法的所有实现,以下语句必须为真。在列表中,
x
y
z
表示不为空的对象引用

  • [……]
  • x.Equals(y)
    返回与
    y.Equals(x)
    相同的值
  • [……]
因此,在方法正确实现的每种情况下,检查都是多余的——这会对每个做了正确事情的开发人员造成性能影响

对于那些没有做正确事情的开发人员来说,它甚至不是非常有用,因为他们可能仍然希望
object.Equals(x,y)
在返回
false
时返回
true
——毕竟,他们可以调试并发现他们的方法返回true。你可以说,它将被记录下来进行双向检查——但我们已经确定,这种影响的唯一开发人员是那些无论如何都不阅读文档的开发人员


基本上,当您重写一个方法或实现一个接口时,您应该知道自己在做什么并遵守指定的约定。如果你不这样做,你会有奇怪的行为,我认为期望每个调用者尝试解决那些没有达到预期目的的实现是不合理的。

如果A等于B,那么我们已经知道B等于A,如果A不等于B,那么B就不能等于A。你为什么希望再进行一次比较呢?任何时候它都会产生不同,基本上,
Equals
的实现都被破坏了。有文件证明,它必须是自反的。@alisabzevari:这会使每个人花费两倍的时间(在平等的情况下),尽管只会影响糟糕的实现。您是否会建议哈希表也应该检查每个条目是否相等,并忽略哈希代码,只是因为有些人也不知道如何实现它?基本上,如果您不遵循要重写的方法的规则,您将引入问题。永远都是这样——没有理由为此惩罚别人。@JonSkeet我不是说惩罚别人。我只是在这里向你们学习,你们是实现.net的人,还有其他有经验的程序员。我一直认为一个好的图书馆必须缩小使用它的范围,以尽量减少阅读文档的需要。关于这个问题,我似乎有太多要学的东西。我当时的想法非常简单和天真!任何不愿意阅读他们正在重写的方法文档以了解它需要做什么的开发人员,在我看来都有很大很大的问题。他们会将我的评论转化为答案。我认为值得一提的是,在
Equals
实现中,一个好的做法是检查两个对象是否共享相同的类型:
obj.GetType().IsAssignableFrom(otherObj.GetType())
。如果是这样的话,就不必担心后面的任何东西都是对称的。@PauloAvelar:我通常会使用
obj.GetType()==otherObj.GetType()
;允许同一层次结构中两个不同类型的实例相等可能会导致问题。很高兴知道。我更精通Java,所以我的直觉是使用
instanceof
:)@PauloAvelar:在Java中,我通常使用
obj.getClass()==otherObj.getClass()
来检查类型是否完全相同。