2009-10-29 12 views
22

मेरे पास अपने स्वयं के संदर्भ-प्रकार ऑब्जेक्ट्स के दो संग्रह हैं जिन्हें मैंने अपना स्वयं का IEquatable लिखा है। इसके लिए विधि, और मैं उन पर LINQ विधियों का उपयोग करने में सक्षम होना चाहता हूं।क्यों नहीं है (LINQ) चीजों की तुलना ठीक से करता है? (IEquatable का उपयोग करके)

तो,

List<CandyType> candy = dataSource.GetListOfCandy(); 
List<CandyType> lollyPops = dataSource.GetListOfLollyPops(); 
var candyOtherThanLollyPops = candy.Except(lollyPops); 

.Except के प्रलेखन, एक IEqualityComparer गुजर नहीं EqualityComparer.Default में परिणाम चाहिए के अनुसार वस्तुओं की तुलना करने के लिए इस्तेमाल किया जा रहा। और डिफ़ॉल्ट comparer के लिए प्रलेखन यह है:।

"डिफ़ॉल्ट संपत्ति चेकों प्रकार टी System.IEquatable सामान्य इंटरफ़ेस लागू करता है और चाहे तो एक EqualityComparer का उपयोग करता है कि कार्यान्वयन अन्यथा यह एक EqualityComparer की ओवरराइड का उपयोग करता है रिटर्न वापस लौट आता है ऑब्जेक्ट। एक्वाल्स एंड ऑब्जेक्ट। गेटहाशकोड टी द्वारा प्रदान किया गया "

तो, क्योंकि मैं अपने वस्तु के लिए IEquatable लागू है, यह है कि और काम का उपयोग करना चाहिए। लेकिन, यह नहीं है। यह तब तक काम नहीं करता जब तक कि मैं GetHashCode को ओवरराइड नहीं करता। असल में, अगर मैं ब्रेक पॉइंट सेट करता हूं, तो मेरी आईक्वाटेबल। एक्वाल्स विधि कभी निष्पादित नहीं होती है। इससे मुझे लगता है कि यह योजना दस्तावेज के अनुसार योजना बी के साथ जा रहा है। मैं समझता हूँ कि अधिभावी GetHashCode वैसे भी एक अच्छा विचार है,, और मैं इस काम के प्राप्त कर सकते हैं, लेकिन मैं परेशान हूँ कि यह एक तरीका है कि क्या अपने स्वयं के प्रलेखन कहा के साथ लाइन में नहीं है में बर्ताव कर रही है।

क्यों नहीं कर रहा है कि वह क्या ने कहा कि यह होता? धन्यवाद।

+0

कोशिश EqualityComparer.Default सीधे का उपयोग कर और अगर बेमेल कि कार्यान्वयन में है देखते हैं, या Linq विधि के साथ, शुरुआत के लिए। फिर परावर्तक खोलें और स्रोत की जांच करें और एमएसडीएन दस्तावेज़ों पर एक टिप्पणी जोड़ें? – MichaelGG

+0

एक साइड नोड के रूप में, दस्तावेजों के रूप में व्यवहार नहीं करने वाली चीजें बग मानी जाती हैं, इसलिए मैं आपको इसे माइक्रोसॉफ्ट कनेक्ट जैसे सबमिट करने के लिए प्रोत्साहित करता हूं। रिकॉर्ड के लिए, मेरे पास अतीत में तय किए गए चैनल के माध्यम से सबमिट की गई छोटी प्रलेखन बग हैं। –

उत्तर

17

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

Is there a complete IEquatable implementation reference?

http://msdn.microsoft.com/en-us/library/ms131190.aspx

http://blogs.msdn.com/irenak/archive/2006/07/18/669586.aspx

+0

एक्सेप्ट स्टेटमेंट विशेष रूप से गेटहाशकोड विधि का उपयोग करता है यह जांचने के लिए कि क्या दो ऑब्जेक्ट्स को समान माना जाना चाहिए, यही कारण है कि यदि आप पूरी तरह से IEquatable को लागू नहीं करते हैं तो यह असफल हो जाएगा –

0

एक अनुमान hazarding, इन विभिन्न वर्गों रहे हैं? मुझे लगता है कि डिफ़ॉल्ट रूप से IEquatable केवल उसी वर्ग के साथ काम करता है। तो यह ऑब्जेक्ट पर वापस गिर सकता है। एक्वाल विधि।

bool Equals(T x, T y); 
int GetHashCode(T obj); 

इस इंटरफेस का एक अच्छा कार्यान्वयन इस प्रकार दोनों को क्रियान्वित करेगी:

+0

विभिन्न कक्षाएं क्या हैं? मैंने इस संग्रह को संग्रह में वस्तुओं के प्रकारों के बारे में अधिक स्पष्ट होने के लिए संपादित किया। उम्मीद है कि मदद करता है। –

10

इंटरफ़ेस IEqualityComparer<T> इन दोनों तरीकों है। लिंक एक्सटेंशन विधि को छोड़कर हैश कोड पर निर्भर करता है ताकि किसी ऑब्जेक्ट का उपयोग किया जा सके या आंतरिक रूप से लुकअप को सेट किया जा सके ताकि यह पता लगाया जा सके कि कौन से ऑब्जेक्ट्स को छोड़ना है, और इस प्रकार उचित गेटहाशकोड कार्यान्वयन की आवश्यकता है।

दुर्भाग्य से, जब आप EqualityComparer<T>.Default उपयोग करते हैं, उस वर्ग के लिए एक अच्छा GetHashCode कार्यान्वयन से ही प्रदान नहीं करता है, और प्रश्न, प्रकार टी में वस्तु पर निर्भर करता है, वह हिस्सा प्रदान करने के लिए, जब यह पता लगाता है कि वस्तु को लागू करता है IEquatable<T>

समस्या यहाँ IEquatable<T> वास्तव में नहीं घोषित करता है कि GetHashCode तो यह बहुत आसान है कि विधि ठीक से, Equals विधि है कि यह घोषणा करता है के साथ विषम लागू करने के लिए भूल जाते हैं के लिए है।

तो तुम दो विकल्प हैं:

  • एक उचित IEqualityComparer<T> कार्यान्वयन को लागू करता है कि दोनों Equals और GetHashCode
  • सुनिश्चित करें कि आपके वस्तु पर IEquatable<T> को लागू करने के अलावा, एक उचित GetHashCode रूप में अच्छी तरह
  • लागू बनाओ प्रदान करें
+1

स्पष्ट होने के लिए, मैंने IEqualityComparer को बिल्कुल लागू नहीं किया - केवल IEquatable । पसंद 1 के लिए, मेरी समझ यह है कि अगर मैंने अपना खुद का तुलनाकर्ता बनाया है जो IEqualityComparer लागू करता है, तो मुझे उस कोडर को प्रत्येक LINQ विधि में कभी भी उपयोग करना होगा, जो मैंने कभी भी उपयोग किया है। वह आकर्षक नहीं है। मुझे लगता है कि आपने जो कुछ भी कहा है वह सच है, लेकिन यह पता नहीं लगाता कि क्यों दस्तावेज़ दस्तावेज की तरह काम नहीं करते हैं (विशेष रूप से, मेरे IEquatable । विधि विधि कभी नहीं बुलाया जाता है)। –

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