在IEquatable 实现中是必要的引用检查

我有一个imquments IEquatable 。 是否有必要在Equals()进行参考检查,还是在框架中进行处理?

 class Foo : IEquatable { int value; Bar system; bool Equals(Foo other) { return this == other || ( value == other.value && system.Equals(other.system) ); } } 

在上面的例子中this==other语句是多余的还是必要的?

更新1

我理解我需要更正代码如下:

  bool Equals(Foo other) { if( other==null ) { return false; } if( object.ReferenceEquals(this, other) ) { return true; } //avoid recursion return value == other.value && system.Equals(other.system); } 

谢谢你的回复。

我认为这是必要的。 参考检查是比较对象时可以执行的第一个快速步骤。

在您给出的示例中,请确保在访问其值之前检查其他值是否为null。

 bool Equals(Foo other) { if(other == null) return false; if(this == other) return true; // Custom comparison logic here. } 

它通常是一种优化 – 它将是一个奇怪的Equals实现,没有它就会失败。 因此,我认为这是必要的 – 但也不是“在框架中照顾”。 我是一个廉价的优化实现,所以它通常值得包括。

请注意,如果您还要重载== ,那么您应该使用object.ReferenceEquals来执行这些比较。

小心。 我实际上强烈反对这一点,因为如果你想在Equals方面为你的Foo类型重载==运算符(通常根据我的经验),你会发现自己有一个无限递归。

为了说明我的意思,这里是Equals ==的通用实现:

 public static bool operator ==(Foo x, Foo y) { // Will overflow the stack if Equals uses ==: return !ReferenceEquals(x, null) && x.Equals(y); } 

也就是说,我完全同意Jon的观点 ,即使用ReferenceEquals可能是合适的。

从某种意义上说,它可能不是正确性所必需的,但框架肯定不会“照顾它”,所以通常出于性能原因,它可能是有用的。

一点:如果实现由EqualityComparer.Default包装,如果其中一个或两个参数为null ,则它不会输入用户代码,因此在这种情况下它会执行一些参考检查(如果不是完整的ReferenceEquals(x, y) )。

 public override bool Equals(T x, T y) { if (x != null) { return ((y != null) && x.Equals(y)); } if (y != null) { return false; } return true; } 

this.system主题,您的示例方法中存在多个空解除引用问题( other可能为nullthis.system可能为null )。

我会把你的方法写成:

 public bool Equals(Foo other) { if(other == null) return false; if(other == this) return true; return value == other.value && EqualityComparer.Default.Equals(bar, other.bar) // You don't *have to* go down the EqualityComparer route // but you do need to make sure you don't dereference null. 

}

还记得每当你编写自己的相等比较时重写GetHashCode

我认为有必要检查this == other ,因为你定义了自己的equals 。 如果您不希望它被指针检查,您可以编写自己的IEquatable

IEquatable是一个接口; 实施取决于实施者。

由于您正在实现接口,因此您负责接口定义的所有预期行为。