【发布时间】:2013-11-07 06:44:23
【问题描述】:
我正在尝试实现一个不可变的Point 类,如果两个Point 实例具有相同的Coordinates,则它们被视为相等。我正在使用 Jon Skeet 的 implementation Coordinate 值类型。
为了比较Points 的相等性,我还继承了EqualityComparer<Point> 和IEquatable<Point>,并且我有一个单元测试如下:
Point.cs:
public class Point : EqualityCompararer<Point>, IEquatable<Point>
{
public Coordinate Coordinate { get; private set; }
// EqualityCompararer<Point>, IEquatable<Point> methods and other methods
}
PointTests.cs:
[Fact]
public void PointReferencesToSamePortalAreNotEqual()
{
var point1 = new Point(22.0, 24.0);
var point2 = new Point(22.0, 24.0);
// Value equality should return true
Assert.Equal(point1, point2);
// Reference equality should return false
Assert.False(point1 == point2);
}
现在我真的被我必须实现的 3 种接口/抽象方法弄糊涂了。它们是:
IEquatable<Point>.Equals(Point other)EqualityComparer<Point>.Equals(Point x, Point y)EqualityComparer<Point>.GetHashCode(Point obj)
而且由于我已经覆盖了IEquatable<Point>.Equals,根据MSDN,我还必须实现:
Object.Equals(object obj)Object.GetHashCode(object obj)
现在我对满足我的单元测试所需的所有Equals 和GetHashCode 方法感到非常困惑(对于point1 和point2,引用相等应该返回false,值相等应该返回true)。
谁能进一步解释一下Equals和GetHashCode?
【问题讨论】:
-
解释关系的简单方法:如果
a.Equals(b) == true然后a.GetHashCode() == b.GetHashCode(),如果a.Equals(b) == false然后a.GetHashCode() == b.GetHashCode() || a.GetHashCode() != b.GetHashCode() -
这个我明白,但我的问题是为什么接口/抽象类?我应该如何实施它们以使其保持一致?
-
您不需要实现
IEqualityComparer,这只是为了将外部类作为特殊情况比较器传入。一个很好的例子:various string comparers 用于忽略大小写之类的事情。IEquatable是这样,你不需要将你的结构装箱在object中进行比较,如果你使用的是类而不是结构,你也不需要 IEquatable。 -
@ScottChamberlain:我实现了
EqualityComparer<T>,因为我在其他使用Point的类中使用了集合(例如,当我调用IEnuermable<Point>.Distinct()时,它将使用我的比较器而不是默认的比较器) -
您所做的就是让默认值按照您想要的方式运行。 EqualityComparer 仅在您想要非默认行为进行比较时使用。