سؤال

ألق نظرة على هذا الفصل:

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 ، فإنني حصلت على هاتين النقطتين سيكون لها نفس الرمز.

هل يمكن لأحد أن يشرح لي لماذا لا يعمل هذا كما كنت أطلب ذلك؟ لست متأكدًا من أنني شرحت هذا جيدًا ، لكن .. أقدر المساعدة: د

جورج

هل كانت مفيدة؟

المحلول

أنت تنفذ 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);
}

تحتاج أيضًا إلى إعادة التفكير في مفهوم "المساواة" ، لأنه لا يجتمع حاليًا .NET نطاق المتطلبات.

إذا كان ذلك ممكنًا ، أوصي بإعادة تصميم مع مستودع من كائنات النقطة التذكارية (ربما يكون مفتاحًا بالاسم) ، بحيث يمكن استخدام المساواة المرجعية البسيطة.

لقد وضعت علامة ArcObjects على هذا ، لذلك اعتقدت فقط أنني أذكر IRELINALOPERATORATOR.Equals. لم أختبر أبدًا لمعرفة ما إذا كانت هذه الطريقة تكرم التسامح العنقودي للمراجع المكانية للهندسة. يمكن تعديل هذا باستخدام ispatialReferencetolerance.xytolerance.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top