StackOverflow 在设计比较运算符时

StackOverflow when designing comparison operators

根据 this article,我将 Equal(Thing) 附上如下。

public override int GetHashCode() { return Id.GetHashCode(); }

public override bool Equals(object input)
{
  Thing comparee = input as Thing;
  return comparee != null && comparee.Id == Id;
}

public static bool operator ==(Thing self, Thing other)
{
  return self != null && other != null && self.Id == other.Id;
}

public static bool operator !=(Thing self, Thing other)
{
  return self == null || other == null || self.Id != other.Id;
}

问题是,在我添加运算符重新定义之前它可以正常工作,但现在我得到 WhosebugException。我错过了什么?

一旦定义了比较 Thing== 运算符,当您说 someThing == null 时就会使用它。同样 !=.

所以如果你说 self == other,你最终会调用 operator ==(self, other)。在你的标准中,你有 self != null,它调用 operator !=(self, null)...它检查是否 self == null,从而调用 operator ==(self, null),然后一圈又一圈直到你 运行 出栈 space.

我很确定您可以通过将内容转换为 object 来解决此问题,以便进行参考比较。或者,你可以说 Object.ReferenceEquals(self, null) 等,它不依赖于 == 所以你不会得到递归。

我完全同意cHao的回答,但是在这种情况下我还想说明一点,所以我将如何实现它:

public static bool operator ==(Thing self, Thing other)
{
    return !ReferenceEquals(self, null) && 
           !ReferenceEquals(other, null) && 
           self.Id == other.Id;
}

public static bool operator !=(Thing self, Thing other)
{
    return !(self == other);
}

使用引用等于不会导致堆栈溢出异常,因为它不使用 == / != 运算符,并且将 != 实现为简单的 return == 运算符的 ! 将为您节省维护,以防等式测试发生变化。这是 DRY 原则的实现。