0

看看这个类:

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 类,它只是两个点和一些其他属性。我不想在我的向量中有相等的点,所以我想出了这个方法:

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

乔治

4

4 回答 4

4

您正在IEqualityComparer<T>尝试比较的类型中实现 - 这很奇怪。几乎可以肯定,您应该只是实施IEquatable<T>和覆盖Equals(object)。那肯定会让你的单元测试工作。

IEquatable<T>和之间的区别在于IEqualityComparer<T>前者是由一个类实现的,说“我可以将自己与同一类型的另一个实例进行比较”。(它不必相同的类型,但通常是。)如果有自然比较,这是合适的 - 例如,选择的比较string是序数相等 - 它必须是完全相同的char值序列。

现在IEqualityComparer<T>不同了——它可以比较一个类型的任何两个实例。对于给定的类型,可以有多种不同的实现,因此特定比较是否是“自然比较”并不重要——它必须是适合您工作的比较。因此,例如,您可以有一个Shape类和不同的相等比较器来按颜色、面积或类似的东西比较形状。

于 2010-06-24T15:55:39.440 回答
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);
}
于 2010-06-24T15:51:33.357 回答
1

您还需要重新考虑您的“平等”概念,因为它目前不符合 .NET框架 要求

如果可能的话,我建议使用纪念点对象的存储库(可能按名称键入)重新设计,以便可以使用简单的引用相等。

于 2010-06-24T16:09:17.060 回答
1

您已经为此添加了 arcobjects 标签,所以我只是想我会提到IRelationalOperator.Equals。我从未测试过这种方法是否符合几何空间参考的集群容差。这可以使用ISpatialReferenceTolerance.XYTolerance进行调整。

于 2010-06-25T14:02:33.557 回答