我有一个Point3d
实现的结构体IEquatable<Point3d>
通过以下方式:
public override bool Equals(object obj) {
return obj is Point3d p && Equals(p);
}
public bool Equals(Point3d other) {
return Equals(other, Tolerance.ToleranceDecimal);
}
public bool Equals(Point3d other, double tolerance) {
if (tolerance < 0) throw new ArgumentOutOfRangeException(nameof(tolerance), tolerance, "Expected a tolerance greater than or equal to 0");
return Math.Abs(X - other.X) <= tolerance && Math.Abs(Y - other.Y) <= tolerance && Math.Abs(Z - other.Z) <= tolerance;
}
public override int GetHashCode() {
var hash = 17;
hash = hash * 23 + X.GetHashCode();
hash = hash * 23 + Y.GetHashCode();
hash = hash * 23 + Z.GetHashCode();
return hash;
}
public static bool operator ==(Point3d firstPoint, Point3d secondPoint) {
return firstPoint.Equals(secondPoint);
}
public static bool operator !=(Point3d firstPoint, Point3d secondPoint) {
return !(firstPoint == secondPoint);
}
这已经在应用程序中大量使用,期望检查两点之间的相等性以允许容差(这是实现正常工作所必需的)。
如果我注意到Equals
and GetHashCode
方法不一致,确实无法写GetHashCode
以能够产生良好且一致结果的形式。在使用 Linq 查询的情况下,此问题尤其成问题,例如points.Distinct()
因为如果直接比较,结果点可能会被认为是相等的,例如points[0] == points[1]
我个人认为最好的选择是改变Equals
如下,使其行为与GetHashCode
:
public bool Equals(Point3d other) {
return Equals(other, 0);
}
然而,由于这已经在应用程序中大量使用,这将是一个重大的突破性变化。我认为这样做是错误的,但我正在考虑改变GetHashCode
to:
public override int GetHashCode() {
return 0;
}
我的理解是,上述内容将迫使Equals
使用的方法会导致性能下降,但也允许在 Linq 查询中将容差内的点视为相等。我想知道这是否会让我陷入任何其他潜在的陷阱。
我不确定还有哪些其他途径可供我使用,因此我非常寻求有关解决此问题的最佳方法的建议。
提前致谢!