الأكثر قوة يساوي التنفيذ لفصول مخصصة للمساواة القيمة في C #

StackOverflow https://stackoverflow.com/questions/570560

  •  05-09-2019
  •  | 
  •  

سؤال

قل لدي فئة نقطة 2، وأريد تنفيذ المساواة التالية:

public override bool Equals ( object obj )

public bool Equals ( Point2 obj )

هذا من كتاب C # 3 الفعال:

public override bool Equals ( object obj )
{
    // STEP 1: Check for null
    if ( obj == null )
    {
        return false;
    }

    // STEP 3: equivalent data types
    if ( this.GetType ( ) != obj.GetType ( ) )
    {
        return false;
    }
    return Equals ( ( Point2 ) obj );
}

public bool Equals ( Point2 obj )
{
    // STEP 1: Check for null if nullable (e.g., a reference type)
    if ( obj == null )
    {
        return false;
    }
    // STEP 2: Check for ReferenceEquals if this is a reference type
    if ( ReferenceEquals ( this, obj ) )
    {
        return true;
    }
    // STEP 4: Possibly check for equivalent hash codes
    if ( this.GetHashCode ( ) != obj.GetHashCode ( ) )
    {
        return false;
    }
    // STEP 5: Check base.Equals if base overrides Equals()
    System.Diagnostics.Debug.Assert (
        base.GetType ( ) != typeof ( object ) );

    if ( !base.Equals ( obj ) )
    {
        return false;
    }

    // STEP 6: Compare identifying fields for equality.
    return ( ( this.X.Equals ( obj.X ) ) && ( this.Y.Equals ( obj.Y ) ) );
}

هل هذا مبالغة؟

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

المحلول

دعم المساواة مع التسلسل الهرمي للميراث أمر صعب. تحتاج إلى العمل بالضبط ما تقصده. هل تحتاج حقا الميراث هنا؟ إذا لم يكن الأمر كذلك - إذا كانت Point2 تستمد مباشرة من System.Opject، ويمكنك أن تجعلها مختومة، تصبح الحياة أسهل بعض الشيء. في هذه الحالة أود استخدامها:

public override bool Equals (object obj)
{
    return Equals(obj as Point2);
}

public bool Equals (Point2 obj)
{
    // STEP 1: Check for null if nullable (e.g., a reference type)
    // Note use of ReferenceEquals in case you overload ==.
    if (object.ReferenceEquals(obj, null))
    {
        return false;
    }

    // STEP 2: Check for ReferenceEquals if this is a reference type
    // Skip this or not? With only two fields to check, it's probably
    // not worth it. If the later checks are costly, it could be.
    if (object.ReferenceEquals( this, obj))
    {
        return true;
    }

    // STEP 4: Possibly check for equivalent hash codes
    // Skipped in this case: would be *less* efficient

    // STEP 5: Check base.Equals if base overrides Equals()
    // Skipped in this case

    // STEP 6: Compare identifying fields for equality.
    // In this case I'm using == instead of Equals for brevity
    // - assuming X and Y are of a type which overloads ==.
    return this.X == obj.X && this.Y == obj.Y;
}

نصائح أخرى

ليس حقا - أنت محاسبة بكثير كل الاحتمالات. إذا كان هذا الرمز مخصص لأي شيء آخر غير تطبيق خدش، فيجب عليك التفكير في فوائد هذا النهج لأن الأخطاء المنطقية بسبب سلوك المساواة بين الكائنات الغريبة مؤلمة لتصحيح الأخطاء.

يبدو لي مثل بالضبط ما تريد. تلك الكتلة كلها تغلي إلى:

"إذا كانت هذه الحالة نفسها بالضبط، فارجع True. إذا كانوا مثيلات منفصلة مع نفس القيم X و Y، فارجع صحيح. جميع الحالات الأخرى (NULL، نوع مختلف، وقيم X / Y مختلفة) إرجاع False".

انها بالتأكيد رمز أكثر من هوية شخصية تريد الكتابة لطريقة تساوي. هناك الكثير من الشيكات الزائدة مثل التحقق من المركبات والاتشكولات الحاشية (أعرف أن هذه الشيكات زائدة عن الحاجة لأن الأسطر الأخيرة في وظيفتك تحقق من المساواة الهيكلية). التركيز على الكود وهو بسيط وقابل للقراءة.

public bool Equals(object o)
{
    Point2 p = o as Point2;
    if (o != null)
        return this.X == o.X && this.Y == o.Y;
    else
        return false;
}

نظرا لأن طريقة التساوي الخاصة بك تستخدم المساواة الهيكلية، فتأكد من تجاوز Gethashcode بتنفيذ بناء على حقولك أيضا.

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