IEquatable और सिर्फ ऑब्जेक्ट ओवरराइडिंग (अंतर) के बीच अंतर क्या है?


183

मैं चाहता हूं कि मेरी Foodकक्षा जब भी किसी अन्य उदाहरण के बराबर हो, परीक्षण कर सके Food। मैं बाद में इसे एक सूची के खिलाफ उपयोग करूंगा, और मैं इसकी List.Contains()विधि का उपयोग करना चाहता हूं । क्या मुझे लागू करना चाहिए IEquatable<Food>या सिर्फ ओवरराइड करना चाहिए Object.Equals()? MSDN से:

यह विधि डिफ़ॉल्ट समानता तुलनित्र का उपयोग करके समानता का निर्धारण करती है, जैसा कि टी के लिए IEquatable.Equals विधि के ऑब्जेक्ट के कार्यान्वयन द्वारा परिभाषित किया गया है (सूची में मूल्यों का प्रकार)।

तो मेरा अगला सवाल यह है: .NET फ्रेमवर्क के कौन से कार्य / वर्ग उपयोग करते हैं Object.Equals()? क्या मुझे इसे पहली जगह में उपयोग करना चाहिए?


3
एक बहुत अच्छी व्याख्या यहाँ blogs.msdn.com/b/jaredpar/archive/2009/01/15/…
nawfal

जवाबों:


213

मुख्य कारण प्रदर्शन है। जब जेनेरिक्स .NET 2.0 में पेश किए गए वे इस तरह के रूप स्वच्छ कक्षाओं का एक समूह जोड़ने के लिए सक्षम थे List<T>, Dictionary<K,V>, HashSet<T>, आदि इन संरचनाओं का भारी उपयोग करते GetHashCodeऔर Equals। लेकिन मूल्य प्रकारों के लिए यह आवश्यक बॉक्सिंग है। IEquatable<T>एक संरचना को दृढ़ता से टाइप की गई Equalsविधि को लागू करने की अनुमति देता है ताकि कोई बॉक्सिंग की आवश्यकता न हो। इस प्रकार सामान्य संग्रह के साथ मूल्य प्रकारों का उपयोग करते समय बहुत बेहतर प्रदर्शन।

संदर्भ प्रकारों से अधिक लाभ नहीं होता है, लेकिन IEquatable<T>कार्यान्वयन आपको एक कास्ट से बचने की अनुमति देता है, System.Objectजिससे यदि इसे अक्सर कहा जाता है, तो इससे फर्क पड़ सकता है।

जैसा कि जेरेड पार्सन के ब्लॉग पर उल्लेख किया गया है , फिर भी आपको ऑब्जेक्ट ओवरराइड को लागू करना होगा।


क्या संदर्भ प्रकारों के बीच कोई कास्ट है? मैं हमेशा सोचता था कि आप केवल "स्टेटमेंट" थे जो आप संकलक को बनाते हैं जब आप कुछ स्पष्ट कास्ट को एक तरह की ऑब्जेक्ट से दूसरे ऑब्जेक्ट में असाइन करते हैं। यह आपके द्वारा संकलित किए जाने के बाद है, कि कोड को यह भी नहीं पता होगा कि वहां कोई कलाकार था।
नटखट एलीसियम

7
यह C ++ में सही है लेकिन .NET लैंग्वेज नहीं है जो टाइप सेफ्टी को लागू करती है। एक रनटाइम कास्ट है और अगर कास्ट सफल नहीं होता है, तो एक अपवाद फेंक दिया जाता है। इसलिए कास्टिंग के लिए भुगतान करने के लिए एक छोटा रनटाइम जुर्माना है। कंपाइलर अपस्टेक को अनुकूलित कर सकता है उदाहरण के लिए ऑब्जेक्ट ओ = (ऑब्जेक्ट) "स्ट्रिंग"; लेकिन डाउनकास्टिंग - स्ट्रिंग एस = (स्ट्रिंग) ओ; - रनटाइम पर होना चाहिए।
जोश

1
समझा। संयोग से आपके पास कोई भी जगह है जहां मैं .NET के बारे में उस तरह की "गहरी" जानकारी प्राप्त कर सकता हूं? धन्यवाद!
व्यतीत हो चुके एलीसियम

7
मैं जेफ रिक्टर द्वारा सी # के माध्यम से सीएलआर और जॉन स्कीट द्वारा गहराई में सी # की सिफारिश करूंगा। ब्लॉग के लिए, Wintellect ब्लॉग अच्छे हैं, msdn ब्लॉग, आदि
जोश

क्या IEquatable<T>इंटरफ़ेस किसी डेवलपर को public bool Equals(T other) कक्षा या संरचना में सदस्य को शामिल करने के लिए याद दिलाने से ज्यादा कुछ नहीं करता है ? इंटरफ़ेस की उपस्थिति या अनुपस्थिति रन-टाइम पर कोई अंतर नहीं डालती है। का अधिभार Equalsवह सब प्रतीत होगा जो आवश्यक है।
मिकेमाय

47

MSDN के अनुसार :

यदि आप कार्यान्वित करते हैं IEquatable<T>, तो आपको बेस क्लास कार्यान्वयन को भी ओवरराइड करना चाहिए Object.Equals(Object)और GetHashCode ताकि उनका व्यवहार IEquatable<T>.Equals विधि के अनुरूप हो । यदि आप ओवरराइड करते हैं Object.Equals(Object), तो आपके ओवरराइड कार्यान्वयन Equals(System.Object, System.Object)को आपकी कक्षा पर स्थैतिक विधि के लिए कॉल भी कहा जाता है । यह सुनिश्चित करता है कि Equalsविधि के सभी इनवोकेशन लगातार परिणाम देते हैं।

तो ऐसा लगता है कि दोनों के बीच कोई वास्तविक कार्यात्मक अंतर नहीं है सिवाय इसके कि या तो यह कहा जा सकता है कि कक्षा का उपयोग कैसे किया जाता है। प्रदर्शन के दृष्टिकोण से, सामान्य संस्करण का उपयोग करना बेहतर है क्योंकि इसके साथ कोई बॉक्सिंग / अनबॉक्सिंग जुर्माना नहीं है।

तार्किक दृष्टिकोण से, इंटरफ़ेस को लागू करना भी बेहतर है। ऑब्जेक्ट को ओवरराइड करना वास्तव में किसी को भी नहीं बताता है कि आपकी कक्षा वास्तव में समान है। ओवरराइड केवल एक वर्ग या उथले कार्यान्वयन के लिए कुछ नहीं हो सकता है। इंटरफ़ेस का उपयोग करना स्पष्ट रूप से कहता है, "अरे, यह चीज़ समानता की जाँच के लिए मान्य है!" यह सिर्फ बेहतर डिजाइन है।


9
यदि वे एक शब्दकोश या इसी तरह के संग्रह में कुंजियों के रूप में उपयोग करने जा रहे हैं, तो संरचनाओं को निश्चित रूप से iEquitable (उनकेOwnType के) को लागू करना चाहिए; यह एक प्रमुख प्रदर्शन को बढ़ावा देगा। गैर-निहित वर्गों को IEquitable (उनकेOwnType के) को लागू करके एक मामूली प्रदर्शन को बढ़ावा मिलेगा। निहित वर्गों को // नहीं // IEquitable को लागू करना चाहिए।
सुपरकैट

30

जोश ने एक व्यावहारिक उदाहरण के साथ कहा। +1 से जोश - मैं अपने उत्तर में वही लिखने वाला था।

public abstract class EntityBase : IEquatable<EntityBase>
{
    public EntityBase() { }

    #region IEquatable<EntityBase> Members

    public bool Equals(EntityBase other)
    {
        //Generic implementation of equality using reflection on derived class instance.
        return true;
    }

    public override bool Equals(object obj)
    {
        return this.Equals(obj as EntityBase);
    }

    #endregion
}

public class Author : EntityBase
{
    public Author() { }
}

public class Book : EntityBase
{
    public Book() { }
}

इस तरह, मेरे पास फिर से उपयोग करने योग्य समान () विधि है जो मेरे सभी व्युत्पन्न वर्गों के लिए बॉक्स से बाहर काम करती है।


बस एक और सवाल। (EntityBase) obj के बजाय "obj as EntityBase" का उपयोग करने से क्या फायदा है? बस स्टाइल की बात है या इसका कोई फायदा है?
व्यतीत हो चुके एलीसियम

22
अगर "EntityBase के रूप में obj" के मामले में - यदि obj EntityBase का नहीं है, तो यह "null" पास हो जाएगा और बिना किसी त्रुटि या अपवाद के जारी रहेगा, लेकिन "(EntityBase) obj" के मामले में, यह बलपूर्वक obj को डालने का प्रयास करेगा। EntityBase और यदि obj EntityBase का नहीं है, तो यह InvalidCastException को फेंक देगा। और हाँ, "जैसा" केवल संदर्भ प्रकारों पर लागू किया जा सकता है।
यह। __curious_geek 6

1
Jared Par के ब्लॉग पर जोश का लिंक आपको लगता है कि GetHashCode को ओवरराइड करने की आवश्यकता है। क्या यह मामला नही है?
एमिकेबल

3
मुझे वास्तव में वह अतिरिक्त मूल्य नहीं मिलता जो आपके कार्यान्वयन को प्रदान करता है। क्या आप इस समस्या को स्पष्ट कर सकते हैं कि आपका सार आधार वर्ग हल करता है?
मर्ट अक्ककाया

1
@ सक्षम - हाँ, जब भी आप Object.Equals (ऑब्जेक्ट) को ओवरराइड करते हैं, तो आपको GetHashCode को भी ओवरराइड करना चाहिए ताकि कंटेनर काम करें।
namford

0

अगर हम कहते हैं object.Equals, तो यह मूल्य प्रकारों पर महंगी मुक्केबाजी करने के लिए मजबूर करता है। यह प्रदर्शन के प्रति संवेदनशील परिदृश्यों में अवांछनीय है। समाधान का उपयोग करना है IEquatable<T>

public interface IEquatable<T>
{
  bool Equals (T other);
}

इसके पीछे विचार IEquatable<T>यह है कि यह उतना ही परिणाम देता है, object.Equalsलेकिन अधिक तेज़ी से। where T : IEquatable<T>नीचे दिए गए सामान्य प्रकारों के साथ अवरोध का उपयोग किया जाना चाहिए।

public class Test<T> where T : IEquatable<T>
{
  public bool IsEqual (T a, T b)
  {
    return a.Equals (b); // No boxing with generic T
  }
}

अन्यथा, यह बांधता है slower object.Equals()

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.