看看这堂课:
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();
}
}
我还有一个Vector类,它只是两个点和一些其他属性。我不想在我的Vector中有相同的分数,所以我想出了这个方法:
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
乔治
答案 0 :(得分:4)
您正在尝试比较的类型中实现IEqualityComparer<T>
- 这很奇怪。您几乎肯定只是实施IEquatable<T>
而是覆盖Equals(object)
。这肯定会使你的单元测试工作。
IEquatable<T>
和IEqualityComparer<T>
之间的区别在于前者是由一个类实现的,“我可以将我自己与另一个相同类型的实例进行比较。” (它不是有是相同的类型,但通常是。)如果有自然比较,这是合适的 - 例如,string
选择的比较是序数相等 - 它必须与char
值完全相同。
现在IEqualityComparer<T>
是不同的 - 它可以比较任何两个类型的实例。对于给定类型,可以有多种不同的实现方式,因此,特定的比较是否是“自然的”并不重要 - 它只是适合您的工作。例如,你可以有一个Shape
类,以及不同的相等比较器,用颜色,面积或类似的东西来比较形状。
答案 1 :(得分:1)
您还需要覆盖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);
}
答案 2 :(得分:1)
您还需要重新考虑您的“平等”概念,因为它目前不符合.NET framework requirements。
如果可能的话,我建议使用纪念点对象的存储库(可能通过名称键控)重新设计,以便可以使用简单的引用相等。
答案 3 :(得分:1)
你在这上面放了一个arcobjects标签,所以我想我会提到IRelationalOperator.Equals。我从未测试过这种方法是否符合几何空间参考的簇容差。这可以使用ISpatialReferenceTolerance.XYTolerance进行调整。