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 原则的实现。
根据 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 原则的实现。