2008-09-16 6 views
6

संदर्भ प्रकारों के लिए समानता() कार्यान्वित करना ऐसा लगता है जितना कठिन लगता है। मेरे वर्तमान विहित कार्यान्वयन इस प्रकार है:संदर्भ प्रकारों के लिए बराबर() के "सर्वोत्तम" कैननिकल कार्यान्वयन क्या है?

public bool Equals(MyClass obj) 
{ 
    // If both refer to the same reference they are equal. 
    if(ReferenceEquals(obj, this)) 
    return true; 

    // If the other object is null they are not equal because in C# this cannot be null. 
    if(ReferenceEquals(obj, null)) 
    return false; 

    // Compare data to evaluate equality  
    return _data.Equals(obj._data); 
} 

public override bool Equals(object obj) 
{ 
    // If both refer to the same reference they are equal. 
    if(ReferenceEquals(obj, this)) 
    return true; 

    // If the other object is null or is of a different types the objects are not equal. 
    if(ReferenceEquals(obj, null) || obj.GetType() != GetType()) 
    return false; 

    // Use type-safe equality comparison 
    return Equals((MyClass)obj); 
} 

public override int GetHashCode() 
{ 
    // Use data's hash code as our hashcode 
    return _data.GetHashCode(); 
} 

मुझे लगता है कि यह सब कोने (विरासत और इस तरह के) के मामलों को शामिल किया गया लेकिन मैं गलत हो सकता है। आप लोग क्या सोचते हैं?

उत्तर

4

मैंने कुछ समय पहले इस बारे में काफी व्यापक मार्गदर्शिका लिखी थी। शुरुआत के लिए आपके बराबर कार्यान्वयन को साझा किया जाना चाहिए (यानी एक ऑब्जेक्ट लेना अधिभार एक दृढ़ता से टाइप की गई वस्तु को लेना चाहिए)। इसके अतिरिक्त आपको GetHashCode को ओवरराइड करने की आवश्यकता के कारण आपकी वस्तु जैसे चीजों को अपरिवर्तनीय होना चाहिए। यहाँ और जानकारी:

http://gregbeech.com/blog/implementing-object-equality-in-dotnet

+0

मेरा कार्यान्वयन "साझा" है। जैसा कि आप देख सकते हैं, बराबर (ऑब्जेक्ट) के अंत में बराबर (MyClass) के लिए एक कॉल है। मुझे उत्परिवर्तन और GetHashCode() मुद्दों के बारे में पता है; लेकिन यह एक महत्वपूर्ण अवलोकन है। यह मुझे कई बार थोड़ा सा है। बहुत बुरा है कि केवल "कक्षाएं" पढ़ने की घोषणा करने का कोई "आसान" तरीका नहीं है। –

+0

लिंक अभी के लिए टूट गया है। – Restuta

0

यह इस बात पर निर्भर करता है कि आप एक मूल्य प्रकार या संदर्भ प्रकार लिख रहे हैं या नहीं। एक क्रमबद्ध मान प्रकार के लिए, मैं इसकी अनुशंसा करता हूं: A code snippet for Visual Studio 2005 that implements a skeleton value type adhering to Framework Design Guidelines

+0

मैं जानता हूँ कि मूल्य प्रकार के लिए कार्यान्वयन अलग है कि। मैंने संदर्भ प्रकारों के बारे में पूछा था। –

+0

टूटा लिंक। : | – Restuta

+0

मैंने टूटी हुई लिंक तय की है ... –

0

विरासत के बारे में, मुझे लगता है कि आपको केवल ओओ प्रतिमान को जादू करना चाहिए।

विशेष रूप से, GetType() चेक हटाया जाना चाहिए, यह लाइन के नीचे polymorphism तोड़ सकता है।

+1

मैं असहमत हूं। कल्पना कीजिए कि हमारे पास ऐप्पल और ऑरेंज कक्षाएं हैं जो फल वर्ग से निकलती हैं। अगर हम फलों में बराबर के कार्यान्वयन में GetType() चेक को हटाते हैं, तो हम सेब की तुलना संतरे से तुलना कर सकते हैं जब तक कि प्रत्येक व्युत्पन्न वर्ग बराबर बराबर ओवरराइड() भी ओवरराइड न हो। यह बहुत जल्दी गन्दा हो सकता है। –

0

मैं चक्र के साथ सहमत हूं, विभिन्न प्रकार की वस्तुओं को समान रूप से बराबर होने की अनुमति दी जानी चाहिए यदि उनके पास एक ही डेटा या आईडी है।

public override bool Equals(object obj) 
    { 
     var other = obj as MyClass; 
     if (other == null) return false; 

     return this.data.Equals(other.data); 
    } 
+0

मैं आपसे असहमत हूं। यह हमें संतरे से संतरे की तुलना करने की अनुमति देगा। –

+0

मुद्दा यह है कि शायद आप उन्हें बराबर होना चाहते हैं। GetType चेक प्रॉक्सी के उपयोग की अनुमति नहीं देगा, उदाहरण के लिए; आपके पास 2 समान वस्तुएं होंगी, एक अलग प्रकार के कंटेनर के अंदर लपेटा जाएगा, लेकिन आप उन्हें समान रूप से पहचानना चाहते हैं। –

+0

@ सैंटियागोपालाडिनो: यह अक्सर समानता तुलनाकर्ताओं को परिभाषित करने के लिए समझ में आता है जो 'ऑब्जेक्ट। एक्वाल्स' की तुलना में समानता की एक कमजोर परिभाषा का उपयोग करते हैं। उदाहरण के लिए, .net विभिन्न केस-असंवेदनशील स्ट्रिंग तुलनाकर्ताओं को परिभाषित करता है जो "हैलो" को "हैलो" या "हेल्लो" के बराबर मानते हैं, भले ही तार अलग-अलग हों। ऐसे तुलनाकर्ता अलग-अलग प्रकार के रूप में बराबर वस्तुओं के रूप में स्वीकार कर सकते हैं। मैं एक ऑब्जेक्ट रिलेशन को परिभाषित करने के लिए 'ऑब्जेक्ट। एक्वाल्स' को ओवरराइड करने वाली वस्तुओं की धारणा को बहुत नापसंद करता हूं जो इतनी ढीली है कि अलग-अलग प्रकार की वस्तुओं को असमान की तुलना करने की अनुमति देने के लिए, जब तक कि कोई स्पष्ट रूप से प्रदान नहीं करता ... – supercat

1

बेहतर आशा व्यक्त की कि this._data अशक्त अगर यह भी एक संदर्भ प्रकार है नहीं है:

व्यक्तिगत रूप से, मैं निम्नलिखित का उपयोग करें।

public bool Equals(MyClass obj) 
{ 
    if (obj == null) { 
     return false; 
    } 
    else { 
     return (this._data != null && this._data.Equals(obj._data)) 
         || obj._data == null; 
    } 
} 

public override bool Equals(object obj) 
{ 
    if (obj == null || !(obj is MyClass)) { 
     return false; 
    } 
    else { 
     return this.Equals((MyClass)obj); 
    } 
} 

public override int GetHashCode() { 
    return this._data == null ? 0 : this._data.GetHashCode(); 
} 
+0

आप सही हैं। यह "बराबर" के पीछे अवधारणाओं को साबित करने के लिए सिर्फ एक "कैननिकल" कार्यान्वयन है। मेरा "वास्तविक" कार्यान्वयन आम तौर पर एक्वाल्स (बी) के बजाए बराबर (ए, बी) का उपयोग करके कार्यान्वित किया जाता है। –

संबंधित मुद्दे