iequalityComparer和怪异的结果
-
29-09-2019 - |
题
看看这个课:
public class MemorialPoint:IMemorialPoint,IEqualityComparer<MemorialPoint>
{
private string _PointName;
private IPoint _PointLocation;
private MemorialPointType _PointType;
private DateTime _PointStartTime;
private DateTime _PointFinishTime;
private string _NeighborName;
private double _Rms;
private double _PointPdop;
private double _PointHdop;
private double _PointVdop;
// getters and setters omitted
public bool Equals(MemorialPoint x, MemorialPoint y)
{
if (x.PointName == y.PointName)
return true;
else if (x.PointName == y.PointName && x.PointLocation.X == y.PointLocation.X && x.PointLocation.Y == y.PointLocation.Y)
return true;
else
return false;
}
public int GetHashCode(MemorialPoint obj)
{
return (obj.PointLocation.X.ToString() + obj.PointLocation.Y.ToString() + obj.PointName).GetHashCode();
}
}
我也有一个矢量类别,这仅仅是两个点,还有其他一些侵犯。我不想在矢量中有相等的分数,所以我想到了这种方法:
public void RecalculateVector(IMemorialPoint fromPoint, IMemorialPoint toPoint, int partIndex)
{
if (fromPoint.Equals(toPoint))
throw new ArgumentException(Messages.VectorWithEqualPoints);
this.FromPoint = FromPoint;
this.ToPoint = ToPoint;
this.PartIndex = partIndex;
// the constructDifference method has a weird way of working:
// difference of Point1 and Point 2, so point2 > point1 is the direction
IVector3D vector = new Vector3DClass();
vector.ConstructDifference(toPoint.PointLocation, fromPoint.PointLocation);
this.Azimuth = MathUtilities.RadiansToDegrees(vector.Azimuth);
IPointCollection pointCollection = new PolylineClass();
pointCollection.AddPoint(fromPoint.PointLocation, ref _missing, ref _missing);
pointCollection.AddPoint(toPoint.PointLocation, ref _missing, ref _missing);
this._ResultingPolyline = pointCollection as IPolyline;
}
和这个单元测试,这应该给我一个例外:
[TestMethod]
[ExpectedException(typeof(ArgumentException), Messages.VectorWithEqualPoints)]
public void TestMemoriaVector_EqualPoints()
{
IPoint p1 = PointPolygonBuilder.BuildPoint(0, 0);
IPoint p2 = PointPolygonBuilder.BuildPoint(0, 0);
IMemorialPoint mPoint1 = new MemorialPoint("teste1", p1);
IMemorialPoint mPoint2 = new MemorialPoint("teste1", p2);
Console.WriteLine(mPoint1.GetHashCode().ToString());
Console.WriteLine(mPoint2.GetHashCode().ToString());
vector = new MemorialVector(mPoint1, mPoint1, 0);
}
当我使用相同点时,即Mpoint1,如代码中的异常所示。当我使用mpoint2时,即使是他们的名字和坐标是相同的,也不会抛出例外。我检查了他们的哈希代码,实际上是不同的。基于我在Gethashcode中创建的代码,我提取这两个点具有相同的哈希码。
有人可以向我解释为什么这不像我那样起作用吗?我不确定我是否对此进行了很好的解释,但是..我感谢帮助:D
乔治
解决方案
您正在实施 IEqualityComparer<T>
在试图比较的类型中 - 这很奇怪。您几乎应该肯定只是在实施 IEquatable<T>
和覆盖 Equals(object)
反而。这肯定会使您的单元测试工作。
和...之间的不同 IEquatable<T>
和 IEqualityComparer<T>
是前者是由班级实施的:“我可以比较 我 与同一类型的另一个实例。”(没有 有 是相同的类型,但通常是。)如果有自然的比较,这是适当的 - 例如,比较由 string
是序数平等 - 必须是完全相同的顺序 char
值。
现在 IEqualityComparer<T>
是不同的 - 它可以比较一种类型的任何两个实例。对于给定类型,可能会有多种不同的实现,因此特定比较是否是“自然的” - 它必须是适合您的工作的合适的比较。因此,例如,您可能有一个 Shape
类别和不同的平等比较,以按颜色,区域或类似的方式比较形状。
其他提示
你需要覆盖 Object.Equals
也是。
将其添加到您的实施中:
// In MemorialPoint:
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
MemorialPoint y = obj as MemorialPoint;
if (this.PointName == y.PointName)
return true;
else if (this.PointName == y.PointName && this.PointLocation.X == y.PointLocation.X && this.PointLocation.Y == y.PointLocation.Y)
return true;
else
return false;
}
然后,我将重新设计您的其他实现以使用第一个,并添加适当的空检查。
public bool Equals(MemorialPoint x, MemorialPoint y)
{
if (x == null)
return (y == null);
return x.Equals(y);
}
您已经在此上放了一个Arcobject标签,所以我只是想我会提到 iReLationalOperator.Equals. 。我从未测试过,以查看这种方法是否尊重几何图形的空间参考的群集耐受性。可以使用 iSpatialReferencetOlance.xytolerance.