2017-07-09 5 views
7

पर विचार करें this कोड:Array.Index क्यों है Iquatable की जांच नहीं कर रहा है जैसे सूची <T> करता है?

public static void Main() 
{ 
    var item = new Item { Id = 1 }; 

    IList list = new List<Item> { item }; 
    IList array = new[] { item }; 

    var newItem = new Item { Id = 1 }; 

    var lIndex = list.IndexOf(newItem); 
    var aIndex = array.IndexOf(newItem); 

    Console.WriteLine(lIndex); 
    Console.WriteLine(aIndex); 
} 

public class Item : IEquatable<Item> 
{ 
    public int Id { get; set; } 

    public bool Equals(Item other) => other != null && other.Id == Id; 

} 

परिणाम:

0 
-1 

क्यों परिणाम List<T> और Array के बीच अलग हैं? मुझे लगता है कि यह डिजाइन द्वारा है, लेकिन क्यों?

List<T>.IndexOf के कोड को देखते हुए मुझे और भी आश्चर्य होता है, क्योंकि यह Array.IndexOf पर पोर्ट कर रहा है।

+1

मैंने इस प्रश्न के बारे में बहुत कम पोस्ट लिखा: http://blog.rogatnev.net/2017/07/1 4/इंडेक्सऑफ-साथ-IEquatable.html – Backs

उत्तर

4

कार्यान्वयन:

public static int IndexOf(Array array, object value, int startIndex, int count)

जैसा कि आप देख, यह मूल्य पैरामीटर के रूप में object उपयोग करता है। इस विधि में वहाँ कोड है:

object obj = objArray[index]; 
if (obj != null && obj.Equals(value)) 
    return index; 

classs वस्तुओं के साथ काम करता है, तो यह public virtual bool Equals(object obj) विधि, नहीं सामान्य से एक कहता है।

List वर्ग IndexOf में सामान्य कार्यान्वयन का उपयोग करता:

EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count); 

युपीडी:

public static int IndexOf<T>(T[] array, T value, int startIndex, int count) 

इसलिए, यह सामान्य गुणवत्ता comparer का उपयोग करता http://blog.rogatnev.net/2017/07/14/IndexOf-with-IEquatable.html

: मैं इस समस्या के बारे में एक छोटे से पोस्ट लिखा
+1

यही कारण है कि' IEquatable 'लागू करते समय आपको * हमेशा * को समान (ऑब्जेक्ट)' (और 'GetHashCode' को अलग-अलग कारणों से ओवरराइड करना चाहिए)। बहुत सरल फिक्स: 'सार्वजनिक ओवरराइड बूल बराबर (ऑब्जेक्ट अन्य) => बराबर (आइटम के रूप में अन्य); सार्वजनिक ओवरराइड int GetHashCode() => आईडी; ' –

4

जब Contains, IndexOf, LastIndexOf, और Remove जैसी पद्धतियों में समानता के लिए परीक्षण सामान्य वस्तु संग्रह IEquatable<T> इंटरफ़ेस का उपयोग क्योंकि।

एक ऐरे को <T> के बारे में कुछ भी नहीं पता है, इसलिए यह IEquatable इंटरफ़ेस को लागू या उपयोग नहीं कर सकता है।

इसके बजाय एक ऐरे ऐसी वस्तुओं को रखता है जो सामान्य नहीं हैं। यह एक ऑब्जेक्ट को दूसरे ऑब्जेक्ट की तुलना करने के लिए Equals पर कॉल करेगा क्योंकि सभी ऑब्जेक्ट्स में Equals विधि है जिसे आप ओवरराइड करने के लिए स्वतंत्र हैं।

+0

'टी [] 'जेनेरिक नहीं है? – Shimmy

+0

हां बिल्कुल। 'टी' सामान्य है लेकिन ऐरे नहीं है। ऐरे में वे ऑब्जेक्ट होते हैं जिन्हें टाइप नहीं किया जाता है। इसलिए यह ऑब्जेक्ट का उपयोग करेगा। तुलना के लिए। –

2

List<T>IEquatable<T> इंटरफ़ेस का उपयोग कर सकते हैं, ताकि कोई अपेक्षा के अनुरूप काम कर सके।

सरणी Equals विधि Object से विधि का उपयोग कर रही है और आप उस पर ओवरराइड नहीं कर रहे हैं, बल्कि IEquatable को लागू कर रहे हैं।

public override bool Equals(Object other) => other != null && (other as Item).Id == Id; 

कि एक ही तरह से दोनों ही मामलों के लिए काम करेगा:

तरह Equals को परिभाषित करने की कोशिश करो। सरणी वर्ग कॉल विधि में IndexOf की

+0

आप 'सार्वजनिक ओवरराइड बूल बराबर (ऑब्जेक्ट अन्य) => समान (आइटम के रूप में अन्य) लिखकर कोड डुप्लिकेशंस से बच सकते हैं;', और यह 'N'RullferenceException' को फेंक नहीं देता है, यदि' अन्य' एक गैर-शून्य वस्तु है एक 'आइटम' नहीं। –

+0

या फिर भी '=> अन्य आइटम आइटम है? item.Id == आईडी: झूठी; ' – Shimmy

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