【问题标题】:Strange implementation of Object.EqualsObject.Equals 的奇怪实现
【发布时间】:2015-07-27 14:10:57
【问题描述】:

我正在阅读MSDN documentation about object.Equals。在它提到的备注部分:

如果两个对象不代表同一个对象引用并且 两者都不为空,它调用 objA.Equals(objB) 并返回结果。 这意味着如果 objA 覆盖 Object.Equals(Object) 方法, 调用此覆盖。

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

编辑:当 objA 的类型覆盖 Equals 方法并将其实现为不可预测的东西时,可能会发生奇怪的行为,但 objB 的类型不会覆盖 Equals

【问题讨论】:

  • 如果 A 等于 B,那么我们已经知道 B 等于 A,如果 A 不等于 B,那么 B 不能等于 A。为什么还要进行比较?
  • 任何时候都会有所作为,Equals 的实现基本上被破坏了。据记载,它必须是自反的。
  • @alisabzevari:好吧,这会让每个人都花费两倍的时间(在平等的情况下),尽管只会影响糟糕的实现。您是否会建议哈希表也应该检查每个条目是否相等并忽略哈希码,只是因为有些人也不知道如何实现它?基本上,如果您不遵循要覆盖的方法的规则,就会引入问题。情况总是如此——没有理由为此惩罚其他人。
  • @JonSkeet 我并不是要惩罚别人。我只是在这里学习,向您、在 SO 中实现 .net 和其他经验丰富的程序员的人学习。我一直认为一个好的库必须缩小使用它的方式,以尽量减少阅读文档的需要。关于这个问题,我似乎有太多要学的东西。我当时想的很简单,很天真!
  • 任何不愿意阅读他们覆盖的方法的文档以找出它需要做什么的开发人员都有很大的问题IMO。会将我的评论转化为答案。

标签: c#


【解决方案1】:

基本上,这只会对有缺陷的Equals 实现的开发人员有用。来自documentation

对于Equals(Object) 方法的所有实现,以下陈述必须为真。在列表中,xyz 表示不为空的对象引用。

  • [...]
  • x.Equals(y) 返回与 y.Equals(x) 相同的值。
  • [...]

因此,在正确实施方法的每种情况下,检查都是多余的 - 会对每个做正确事情的开发人员造成性能损失。

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

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

【讨论】:

  • 我认为值得一提的是,Equals 实现中的一个好习惯是检查两个对象是否共享相同的类型:obj.GetType().IsAssignableFrom(otherObj.GetType())。确实如此,不用担心后面发生的任何事情都是对称有效的。
  • @PauloAvelar:我通常会使用obj.GetType() == otherObj.GetType();允许同一层次结构中两种不同类型的实例相等可能会导致问题。
  • 很高兴知道。我更精通Java,所以我的直觉是使用instanceof。 :)
  • @PauloAvelar:在 Java 中,我通常会使用 obj.getClass() == otherObj.getClass() 检查类型是否完全相同。
猜你喜欢
  • 1970-01-01
  • 2015-10-19
  • 2011-07-23
  • 1970-01-01
  • 2015-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多