2011-09-04 10 views
29

क्या मुझे IComparable और सामान्य IComparable<T> दोनों को लागू करना चाहिए? क्या कोई सीमा है यदि मैं केवल उनमें से एक को लागू करता हूं?IComparable और IComparable <T>

+0

आपको केवल 'IComparable ' के लिए कोड लिखने की आवश्यकता है। आपको सामान्य कार्यान्वयन (ओं) की वास्तविक तुलना के प्रतिनिधि द्वारा 'आईसीओम्पेर्बल' मिलता है। –

उत्तर

18

हाँ, आप दोनों को लागू करना चाहिए।

आप एक, किसी भी कोड है कि अन्य पर निर्भर करता है असफल हो जायेगी लागू करते हैं तो।

बहुत सारे कोड हैं जो IComparable या IComparable<T> का उपयोग करते हैं, लेकिन दोनों नहीं, इसलिए यह सुनिश्चित करना कि आपका कोड ऐसे कोड के साथ काम करेगा।

+0

यदि आप सभी कोड को नियंत्रित करते हैं, तो क्या आप यह निर्धारित कर सकते हैं कि आपको केवल सामान्य संस्करण को लागू करने की आवश्यकता है? या क्या कुछ ढांचे के कोड को अभी भी गैर-जेनेरिक संस्करण की आवश्यकता है? –

+0

@ डेविड, कुछ ढांचे वर्ग (जैसे संग्रह) एक या दूसरे पर भरोसा कर सकते हैं। –

+5

@ डेविड - 'आईकॉम्परेबल' निश्चित रूप से कुछ ढांचे कोड द्वारा उपयोग किया जाता है। मेरा मानना ​​है कि 'Array.Sort' और' ArrayList.Sort' इसका उपयोग करते हैं। – Oded

4

जबकि IEquatable < टी > आम तौर पर असीमित वर्गों द्वारा लागू नहीं किया जाना चाहिए, क्योंकि इस तरह की व्युत्पत्ति विरासत के साथ विचित्र रूप से खेलती है जब तक कि कार्यान्वयन केवल ऑब्जेक्ट.क्वाल्स (जिस स्थिति में यह व्यर्थ नहीं होगा), विपरीत स्थिति उत्पन्न होती है जेनेरिक आईसीओम्पेर्बल < टी >। Object.Equals और IEquatable < टी > के लिए अर्थ विज्ञान मतलब है कि जब भी IEquatable < टी > परिभाषित किया गया है, उसके व्यवहार Object.Equals की कि दर्पण चाहिए (एक तरफ संभवतः तेजी से किया जा रहा है और मुक्केबाजी से परहेज से)। DerivedFoo प्रकार की दो ऑब्जेक्ट्स जो कि डेरिवेटफू प्रकार के रूप में मानी जाती है, उतनी ही तुलना की जाती है जब फू प्रकार की वस्तुओं के रूप में माना जाता है, और इसके विपरीत। दूसरी तरफ, यह पूरी तरह से संभव है कि DerivedFoo प्रकार के दो ऑब्जेक्ट्स जो समान रूप से रैंक करते हैं, टाइप प्रकार के रूप में माना जाता है जब टाइप Foo के रूप में माना जाता है। इसका आश्वासन देने का एकमात्र तरीका आईसीओपरपेबल < टी > का उपयोग करना है।

मान लीजिए, उदाहरण के लिए, एक वर्ग शेड्यूलरइवेंट है जिसमें फ़ील्ड शेड्यूल्डटाइम (टाइप डेटटाइम का प्रकार) और अनुसूचित एक्शन (प्रकार MethodInvoker) शामिल है। कक्षा में सबटाइप शेड्यूलरएवेंट विथमेसेज (जो टाइप स्ट्रिंग का संदेश फ़ील्ड जोड़ता है) और शेड्यूलरएवेंट विथगोंग (जो डबल प्रकार का गोंगवॉल्यूम फ़ील्ड जोड़ता है) शामिल है। शेड्यूलरवेन्ट क्लास में शेड्यूलटाइम द्वारा प्राकृतिक ऑर्डरिंग होती है, लेकिन यह उन घटनाओं के लिए पूरी तरह से संभव है जो एक-दूसरे के साथ असमान होने के समान नहीं हैं। शेड्यूलरइवेंट विथ मैसेज और शेड्यूलर इवेंट विथगोंग कक्षाओं में भी अपने बीच प्राकृतिक क्रम हैं, लेकिन क्लास शेड्यूलरएवेंट की वस्तुओं की तुलना में नहीं।

मान लीजिए कि एक के पास दो शेड्यूलर इवेंट विथ मैसेज इवेंट एक्स और वाई एक ही समय के लिए निर्धारित हैं, लेकिन एक्स। मैसेज "आर्डवर्र्क" है और वाई मैसेज "ज़िमूरजी" है। ((IComparable < शेड्यूलरएवेंट >) एक्स)। कॉम्पैर करने के लिए (वाई) शून्य की रिपोर्ट करनी चाहिए (क्योंकि घटनाओं के बराबर समय है) लेकिन ((आईसीओम्परेबल < शेड्यूलरएवेंट विथ मैसेज >) एक्स)। कॉम्पैयर (वाई) को ऋणात्मक संख्या वापस करनी चाहिए (चूंकि "आर्डवर्र्क" "zymurgy" से पहले प्रकार)। यदि वर्ग इस तरह से व्यवहार नहीं करता है, तो एक सूची को क्रमशः क्रमबद्ध करना असंभव या असंभव होगा जिसमें शेड्यूलरएवेंट विथ मैसेज और शेड्यूलरएवेंट विथगोंग ऑब्जेक्ट्स का मिश्रण शामिल है।

संयोग से, कोई तर्क दे सकता है कि यह IEquatable < टी > के अर्थशास्त्र की तुलना में उपयोगी होगा, वस्तुओं की तुलना केवल प्रकार टी के सदस्यों के आधार पर करें, ताकि उदा। IEquatable <SchedulerEvent> समानता के लिए ScheduledTime और ScheduledAction जाँच करेगा, लेकिन तब भी जब एक SchedulerEventWithMessage के लिए आवेदन किया या SchedulerEventWithGong संदेश या GongVolume गुण जाँच नहीं होता। दरअसल, वे एक आईक्वेटेबल < टी > विधि के लिए उपयोगी अर्थशास्त्र होंगे, और मैं इस तरह के अर्थशास्त्र का पक्ष लेगा, लेकिन एक समस्या के लिए: तुलनात्मक < टी >। डीफॉल्ट.गेटहाशकोड (टी) हमेशा एक ही फ़ंक्शन ऑब्जेक्ट.गेटहाशकोड() को कॉल करता है प्रकार टी यह बहुत अलग अलग प्रकार के साथ अपने व्यवहार भिन्न करने IEquatable < टी > की क्षमता को सीमित करता है टी

+0

बहुत ही रोचक जवाब। –

19

ओड सही है कि आपको दोनों को लागू करना चाहिए क्योंकि संग्रह और अन्य वर्ग हैं जो केवल कार्यान्वयन पर भरोसा करते हैं।

लेकिन वहां एक चाल है: IComparable < टी > अपवाद नहीं फेंकना चाहिए, जबकि IComparable चाहिए। IComparable < टी > लागू करने पर आप यह सुनिश्चित करने के लिए प्रभारी हैं कि टी के सभी उदाहरणों की तुलना एक दूसरे के खिलाफ की जा सकती है। इसमें शून्य भी शामिल है (टी के सभी गैर-शून्य उदाहरणों से छोटे के रूप में शून्य का इलाज करें और आप ठीक होंगे)।

हालांकि, सामान्य आईसीओपरपेबल सिस्टम स्वीकार करता है। ऑब्जेक्ट और आप गारंटी नहीं दे सकते कि सभी कल्पनीय वस्तुएं टी के उदाहरणों के मुकाबले तुलनीय होंगी। इसलिए, यदि आपको गैर-टी उदाहरण आईसीओपरपेबल को पास किया जाता है, तो बस सिस्टम को फेंक दें। ऑर्ग्यूमेंट अपवाद । अन्यथा, कॉल को IComparable < टी > कार्यान्वयन पर रूट करें।

यहाँ उदाहरण है:

public class Piano : IComparable<Piano>, IComparable 
{ 
    public int CompareTo(Piano other) { ... } 
    ... 
    public int CompareTo(object obj) 
    { 

     if (obj != null && !(obj is Piano)) 
      throw new ArgumentException("Object must be of type Piano."); 

     return CompareTo(obj as Piano); 

    } 
} 

यह उदाहरण जो दुष्प्रभाव के विस्तृत विश्लेषण है कि आप जब IComparable < टी > को लागू करने का ध्यान रखना चाहिए होता है एक बहुत लंबे समय तक लेख का हिस्सा है: How to Implement IComparable<T> Interface in Base and Derived Classes

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