2008-10-21 13 views
32

यह एक पुराना प्रश्न हो सकता है: IEnumerable<T>IEnumerable से क्यों प्राप्त होता है?IENumerable <T> IENumerable से क्यों प्राप्त होता है?

इस तरह .NET करता है, लेकिन यह थोड़ा परेशानी लाता है। हर बार जब मैं कक्षा लिखता हूं IEumerable<T> लागू करता है, तो मुझे दो GetEnumerator() फ़ंक्शंस लिखना होगा, एक IEnumerable<T> और दूसरा IEnumerable के लिए।

और, IList<T> IList से प्राप्त नहीं है।

मुझे नहीं पता कि क्यों IEnumerable<T> अन्य तरीकों से डिज़ाइन किया गया है।

उत्तर

48

Straight from the horse's mouth (Hejlsberg):

आदर्श रूप में सामान्य संग्रह इंटरफेस के सभी (ICollection<T> जैसे, IList<T>) उनके गैर सामान्य समकक्षों से विरासत हैं ऐसी है कि सामान्य इंटरफ़ेस उदाहरणों सामान्य और गैर के साथ दोनों इस्तेमाल किया जा सकता जेनेरिक कोड उदाहरण के लिए, यह सुविधाजनक होगा अगर IList<T> को कोड पर पास किया जा सकता है जो IList की अपेक्षा करता है।

यह पता चला है के रूप में, केवल सामान्य इंटरफ़ेस है जिसके लिए यह संभव है, IEnumerable<T> है, क्योंकि केवल IEnumerable<T> विपरीत संस्करण है: IEnumerable<T> में, प्रकार पैरामीटर टी केवल "उत्पादन" की स्थिति में (वापसी मान) और नहीं प्रयोग किया जाता है "इनपुट" पदों (पैरामीटर) में। ICollection<T> और IList<T> इनपुट और आउटपुट स्थितियों दोनों में टी का उपयोग करें, और वे इंटरफेस इसलिए परिवर्तनीय हैं। (एक अलग रूप में, वे विपरीत संस्करण होता है, तो टी केवल इनपुट की स्थिति में इस्तेमाल किया गया था, लेकिन वह वास्तव में बात यहाँ नहीं करता है।)

< ... स्निप ...>

तो, अपने प्रश्न का उत्तर देने के लिए, IEnumerable<T>IEnumerable से विरासत प्राप्त करता है क्योंकि यह कर सकता है! :-)

+1

यह दिलचस्प है ... मैं वास्तव में नाराज था कि 'IList ' 'IList' का उत्तराधिकारी नहीं था, लेकिन जैसे ही आप खाते में भिन्नता लेते हैं, यह समझ में आता है ... –

+1

यह बहुत बुरा है माइक्रोसॉफ्ट ने कभी भी इरेडेबलबीइंडेक्स और आईआरडेबलबइंडेक्स को परिभाषित नहीं किया (आउट टी), जो IList और IList (टी के) द्वारा विरासत में प्राप्त किया जा सकता था। IReadableByIndex को बिना किसी कठिनाई के इरडेबलबीइंडेक्स (टी) द्वारा विरासत में मिलाया जा सकता है, और केवल-पढ़ने योग्य सूचकांक संग्रह का अंतर बहुत अच्छा रहा होगा। – supercat

+0

@supercat माइक्रोसॉफ्ट ने आपकी प्रार्थनाएं सुनी होंगी, क्योंकि आपने उस टिप्पणी को लिखा है, इसलिए उन्होंने ['IReadOnlyList '] (http://msdn.microsoft.com/en-us/library/hh192385.aspx) पेश किया है, जहां 'आउट' 'टी' में कॉन्वर्सिस का प्रतीक है। –

16

IEnumerable का उत्तर है: "क्योंकि यह प्रकार की सुरक्षा को प्रभावित किए बिना कर सकता है"।

IEnumerable एक "केवल पढ़ने योग्य" इंटरफेस है - इसलिए इससे कोई फर्क नहीं पड़ता कि जेनेरिक रूप नोंगनेरिक रूप से अधिक विशिष्ट है। आप दोनों को लागू करके कुछ भी नहीं तोड़ते हैं। IEnumerator.Currentobject देता है, जबकि IEnumerator<T>.CurrentT देता है - ठीक है, क्योंकि आप हमेशा वैध रूप से object में परिवर्तित कर सकते हैं, हालांकि इसका मतलब मुक्केबाजी हो सकता है।

IList<T> और IList के साथ इस की तुलना करें - आप एक IList पर Add(object) कॉल कर सकते हैं, जबकि कि अच्छी तरह से किसी विशेष IList<T> (वास्तव में IList<object> के अलावा और कुछ) के लिए अमान्य हो सकता है।

ब्रैड अब्राम के blogged with Anders' answer इस सवाल के बारे में।

2

ऐसा इसलिए है कि यह उन वर्गों के साथ काम करेगा जो जेनेरिक का समर्थन नहीं करते हैं। इसके अतिरिक्त, .NET जेनेरिक आपको आईएलआईस्ट < लांग> जैसे IList < int> के रूप में चीजों को करने की अनुमति नहीं देते हैं, इसलिए इंटरफेस के गैर सामान्य संस्करण काफी उपयोगी हो सकते हैं जब आपको निश्चित बेस क्लास या इंटरफ़ेस की आवश्यकता होती है।

+0

यह एक महत्वपूर्ण बात है। IList को IList पर नहीं डाला जा सकता है। –

3

यह पिछड़ा संगतता के लिए है। यदि आप .NET 1 को कॉल करते हैं।1 फ़ंक्शन जो एक वेनिला आईनेमरेबल की अपेक्षा करता है आप अपने जेनेरिक आईनेमेरेबल में पास कर सकते हैं।

Luckilly सामान्य IEnumerator पुरानी शैली IEnumerator

मैं आमतौर पर एक निजी विधि है कि एक प्रगणक रिटर्न को लागू करने और फिर दोनों पुराने और नए शैली GetEnumerator विधि के लिए इसे पारित से विरासत।

private IEnumerator<string> Enumerator() { 
     // ... 
    } 

    public IEnumerator<string> GetEnumerator() { 
     return Enumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { 
     return Enumerator(); 
    } 
+0

IENumerable को कार्यान्वित करते समय, आपको निजी IEnumerable.GetEnumerator() विधि को भी लागू करने की आवश्यकता होती है। सौभाग्य से, ऊपर दिया गया कोड अच्छी तरह से करता है, इसलिए आप प्रयास को डुप्लिकेट नहीं कर रहे हैं। – spoulson

+2

@spoulson: निजी नहीं है। यह एक इंटरफ़ेस का हिस्सा है, इसलिए इसे सार्वजनिक रूप से कार्यान्वित किया जाना चाहिए। मेंडेल का उदाहरण इसे निजी रूप से कार्यान्वित नहीं करता है, यह स्पष्ट रूप से लागू करता है, ताकि यह केवल तभी उपलब्ध हो जब ऑब्जेक्ट को आईन्यूमेरेबल में डाला जा सके। –

+0

@ स्पॉल्सन: दृश्य स्टूडियो में इंटरफ़ेस को कार्यान्वित करने पर क्लिक करने पर दूसरी दो विधियां उत्पन्न हुईं, वास्तव में इसे नहीं देखा। आप बस सिस्टम के लिए एक उपयोग जोड़ सकते हैं। चयन और तीसरे कार्य को स्पष्ट रूप से सार्वजनिक बनाते हैं। – Mendelt

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