C# object ليست فارغة ولكن (myObject != null) لا يزال return false

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

  •  03-07-2019
  •  | 
  •  

سؤال

أنا بحاجة إلى القيام comparaison بين كائن NULL.عند الكائن ليست فارغة أنا ملء مع بعض البيانات.

هنا هو رمز :

 if (region != null)
 {
  ....
 }

هذا هو العامل ولكن عندما حلقات وحلقات وقت المنطقة الكائن ليست فارغة (أستطيع أن أرى البيانات داخله في وضع التصحيح).في خطوة بخطوة عند التصحيح, لا تذهب في الداخل إذا كان البيان...عندما أقوم سريعة ووتش مع هذه التعبير التالي :أرى (المنطقة == null) return false, و (المنطقة != null) return false جدا... لماذا و كيف ؟

التحديث

شخص نشير إلى أن الكائن كان == و != مثقلة:

    public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }


    public static bool operator !=(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }
        return (r1.Cmr.CompareTo(r2.Cmr) != 0 || r1.Id != r2.Id);
    }
هل كانت مفيدة؟

المحلول

هو == و/أو != مشغل طاقتها للمنطقة الكائن الصف ؟

الآن بعد أن كنت قد نشرت مدونة الزائدة:

فإن الزائدة ربما ينبغي أن ننظر مثل التالية (رمز مأخوذة من التعيينات التي أدلى بها جون السكيت و فيليب Rieck):

public static bool operator ==(Region r1, Region r2)
{
    if (object.ReferenceEquals( r1, r2)) {
        // handles if both are null as well as object identity
        return true;
    }

    if ((object)r1 == null || (object)r2 == null)
    {
       return false;
    }        

    return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}

public static bool operator !=(Region r1, Region r2)
{
    return !(r1 == r2);
}

نصائح أخرى

تلك مشغل الزائدة هي مكسورة.

أولا: يجعل الحياة أسهل كثيرا إذا != تنفذ فقط أتصل == وعكس النتيجة.

ثانيا ، قبل بطلان الشيكات == يجب أن يكون هناك:

if (object.ReferenceEquals(r1, r2))
{
    return true;
}

كل من الزائدة غير صحيحة

 public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

إذا r1 و r2 فارغة, أول اختبار (الكائن.ReferenceEquals(r1, null)) سوف return false, على الرغم من r2 هو أيضا باطل.

محاولة

//ifs expanded a bit for readability
 public static bool operator ==(Region r1, Region r2)
    {
        if( (object)r1 == null && (object)r2 == null)
        {
           return true;
        }
        if( (object)r1 == null || (object)r2 == null)
        {
           return false;
        }        
        //btw - a quick shortcut here is also object.ReferenceEquals(r1, r2)

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

هذا يمكن أن يحدث في بعض الأحيان عندما يكون لديك العديد من المواضيع العمل مع نفس البيانات.إذا كانت هذه هي الحالة ، يمكنك استخدام قفل لمنعهم من العبث مع بعضنا البعض.

المساواة مقارنة من نوع "T", الزائد هذه الأساليب:

int GetHashCode() //Overrides Object.GetHashCode
bool Equals(object other) //Overrides Object.Equals; would correspond to IEquatable, if such an interface existed
bool Equals(T other) //Implements IEquatable<T>; do this for each T you want to compare to
static bool operator ==(T x, T y)
static bool operator !=(T x, T y)

الخاص بك نوع معين مقارنة رمز ينبغي أن يتم ذلك في مكان واحد:نوع آمنة IEquatable<T> واجهة الطريقة Equals(T other).إذا كنت مقارنة مع نوع آخر (T2) ، تنفيذ IEquatable<T2> وكذلك وضع مقارنة حقل رمز لهذا النوع يساوي(T2 الأخرى).

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

bool Equals(object other)
{
    if (other is T) //replicate this for each IEquatable<T2>, IEquatable<T3>, etc. you may implement
        return Equals( (T)other) ); //forward to IEquatable<T> implementation
    return false; //other is null or cannot be compared to this instance; therefore it is not equal
}

bool Equals(T other)
{
    if ((object)other == null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return false;
    //if ((object)other == this) //possible performance boost, ONLY if object instance is frequently compared to itself! otherwise it's just an extra useless check
        //return true;
    return field1.Equals( other.field1 ) &&
           field2.Equals( other.field2 ); //compare type fields to determine equality
}

public static bool operator ==( T x, T y )
{
    if ((object)x != null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return false; //x was null, y is not null
    return true; //both null
}

public static bool operator !=( T x, T y )
{
    if ((object)x != null)
        return !x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return true; //x was null, y is not null
    return false; //both null
}

المناقشة:

السابقة تنفيذ يركز على نوع معين (أيمجال المساواة) مقارنة مع نهاية IEquatable<T> تنفيذ نوع.على == و != شركات موازية ولكن العكس التنفيذ.أنا أفضل هذا على وجود مرجعية واحدة أخرى ، مثل أن هناك إضافية أسلوب الدعوة تعتمد واحد.إذا كان != المشغل هو ببساطة الذهاب إلى استدعاء == مشغل بدلا من أن نقدم على قدم المساواة أداء المشغل ، عندها فقط استخدام !(obj1 == obj2) وتجنب إضافية استدعاء الأسلوب.المقارنة إلى النفس تبقى من يساوي المشغل IEquatable<T> تطبيقات, لأنه يمكن أن أعرض 1.لا لزوم لها الحمل في بعض الحالات ، و/أو 2.تتعارض الأداء اعتمادا على كيفية غالبا مثيل مقارنة نفسها مقابل حالات أخرى.

بديل أنا لا أحب, ولكن يجب أن يذكر هو عكس هذا الإعداد ، مركزة على نوع معين المساواة البرمجية في المشغل المساواة بدلا ولها يساوي أساليب تعتمد على ذلك.يمكن بعد ذلك استخدام اختصار ReferenceEquals(obj1,obj2) للتحقق من إشارة المساواة null المساواة في وقت واحد كما ذكر فيليب في آخر في وقت سابق ، إلا أن فكرة مضللة.يبدو انك قتل عصفورين بحجر واحد ، ولكن في الواقع خلق المزيد من العمل-بعد تحديد الأشياء ليست كل لاغية ولا نفس الحالة ، سوف ثم بالإضافة إلى ذلك ، لا تزال بحاجة الى أن تحقق ما إذا كان كل حالة باطل.في تنفيذ, يمكنك التحقق من أي مثيل واحد من كونها فارغة تماما مرة واحدة.بحلول الوقت الذي يساوي سبيل المثال ما يسمى طريقة, انها بالفعل استبعد أن أول كائن يجري مقارنة باطل ، لذلك كل ما تبقى القيام به هو التحقق من ما إذا كان الآخر باطل.وذلك بعد اثنين على الأكثر المقارنات ، نقفز مباشرة في مجال التدقيق ، بغض النظر عن الطريقة التي نستخدم (Equals(object),Equals(T),==,!=).أيضا ، كما ذكرت ، إذا كنت حقا مقارنة و الاعتراض على نفسها معظم الوقت, ثم هل يمكن أن أضيف أن تحقق في أسلوب يساوي فقط قبل الغوص في مجال المقارنات.نقطة في إضافته آخر هو أنه يمكن أن لا تزال تحافظ على تدفق/التبعية الهرمي بدون إدخال زائدة/مجدية تحقق في كل مستوى.

لذلك هو أن هذه الشيكات هنا غير صحيح:

public static bool operator !=(Region r1, Region r2)
{
    if (object.ReferenceEquals(r1, null))
    {
        return false;
    }
    if (object.ReferenceEquals(r2, null))
    {
        return false;
    }
...

هناك احتمال آخر أن تحتاج إلى انقر فوق رمز التحديث القادم إلى المعلمة التي تشاهدها.مقابل محاولة مواكبة الأداء في حين لا تقييم كل بيان/المعلمة.نلقي نظرة على التأكد ، قبل البدء في إجراء تغييرات على الأماكن التي هي غير ذات الصلة.

bool comp;
if (object.IsNullOrEmpty(r1))
{
    comp = false;
}

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top