2011-01-27 8 views
66

List घोषणा:क्यों (वास्तव में यह करता है?) सूची <T> इन सभी इंटरफेस को लागू करें, न केवल IList <T>? MSDN से

public class List<T> : IList<T>, ICollection<T>, 
IEnumerable<T>, IList, ICollection, IEnumerable 

परावर्तक समान तस्वीर देता है। क्या List वास्तव में इन सभी को लागू करता है (यदि हां क्यों)? मैंने जांच की है:

interface I1 {} 
    interface I2 : I1 {} 
    interface I3 : I2 {} 

    class A : I3 {} 
    class B : I3, I2, I1 {} 

    static void Main(string[] args) 
    { 
     var a = new A(); 
     var a1 = (I1)a; 
     var a2 = (I2)a; 
     var a3 = (I3)a; 

     var b = new B(); 
     var b1 = (I1) b; 
     var b2 = (I2)b; 
     var b3 = (I3)b; 
    } 

यह संकलित करता है।

[अपडेट]:

दोस्तों, के रूप में मैं समझता हूँ, सभी उत्तर यह है कि रहने:

class Program 
{ 

    interface I1 {} 
    interface I2 : I1 {} 
    interface I3 : I2 {} 

    class A : I3 {} 
    class B : I3, I2, I1 {} 

    static void I1M(I1 i1) {} 
    static void I2M(I2 i2) {} 
    static void I3M(I3 i3) {} 

    static void Main(string[] args) 
    { 
     var a = new A(); 
     I1M(a); 
     I2M(a); 
     I3M(a); 

     var b = new B(); 
     I1M(b); 
     I2M(b); 
     I3M(b); 

     Console.ReadLine(); 
    } 
} 

त्रुटि देना होगा, लेकिन यह संकलित करता है तथा चलाता किसी भी त्रुटि के बिना। क्यूं कर?

+2

हां सूची उन सभी इंटरफेस को लागू करती है, क्यों - क्योंकि वे सभी सूची संग्रह के लिए प्रासंगिक हैं। आपका कोड क्या है? क्या यह एक अलग सवाल है? –

+0

आपका नमूना कोड 'सूची ' वर्ग के साथ कोई संबंध नहीं है ... – BoltClock

+0

मुझे लगता है कि वह पूछ रहा है क्यों 'सार्वजनिक वर्ग सूची : IList , ICollection , IEnumerable , etc.' बल्कि सिर्फ' सार्वजनिक वर्ग सूची से : IList '। ध्यान दें कि 'आईसीओलेक्शन' और' IList' (गैर-जेनेरिक वाले) को 'IList ' से विरासत में नहीं मिला है। – Rup

उत्तर

129

अद्यतन: यह प्रश्न my blog entry for Monday April 4th 2011 का आधार था। महान सवाल के लिए धन्यवाद।

मुझे इसे कई छोटे प्रश्नों में विभाजित करने दें।

क्या List<T> वास्तव में उन सभी इंटरफेस को लागू करता है?

हां।

क्यों?

क्योंकि जब एक इंटरफेस (जैसे कि, IList<T>) एक अंतरफलक से विरासत (माना IEnumerable<T>) तो अधिक व्युत्पन्न इंटरफ़ेस का कार्यान्वयन भी कम प्राप्त होता इंटरफ़ेस को लागू करने के लिए आवश्यक हैं। यही इंटरफेस विरासत का मतलब है; यदि आप अधिक व्युत्पन्न प्रकार के अनुबंध को पूरा करते हैं तो आपको कम व्युत्पन्न प्रकार के अनुबंध को भी पूरा करना होगा।

तो एक वर्ग को अपने इंटरफेस के पारगमन बंद करने में सभी इंटरफेस के सभी तरीकों को लागू करने की आवश्यकता है?

बिल्कुल।

है एक वर्ग को लागू करने वाली एक और अधिक व्युत्पन्न इंटरफ़ेस भी उसके आधार प्रकार सूची में राज्य के लिए कि यह उन कम व्युत्पन्न इंटरफेस के सभी लागू कर रहा है के लिए आवश्यक?

सं

वर्ग यह राज्य नहीं करने के लिए आवश्यक है?

सं

तो यह वैकल्पिक कि क्या कम व्युत्पन्न कार्यान्वित इंटरफेस आधार प्रकार सूची में कहा गया है कर रहे हैं?

हां।

हमेशा?

लगभग हमेशा:

interface I1 {} 
interface I2 : I1 {} 
interface I3 : I2 {} 

यह है कि क्या I3 कहा गया है कि यह I1 से विरासत वैकल्पिक है। I3 की

class B : I3 {} 

Implementers I2 और I1 को लागू करने के लिए आवश्यक हैं, लेकिन वे स्पष्ट रूप से यह है कि वे ऐसा कर रहे हैं की आवश्यकता नहीं है। यह वैकल्पिक है।

class D : B {} 

व्युत्पन्न कक्षाओं को फिर से यह बताने की आवश्यकता नहीं है कि वे अपनी बेस कक्षा से एक इंटरफेस लागू करते हैं, लेकिन ऐसा करने की अनुमति है। (इस मामले में विशेष है, अधिक जानकारी के लिए नीचे देखें।)

class C<T> where T : I3 
{ 
    public virtual void M<U>() where U : I3 {} 
} 

प्रकार तर्क टी करने के लिए इसी और यू I2 और I1 को लागू करने के लिए आवश्यक हैं, लेकिन यह टी या यू पर बाधाओं कि राज्य के लिए के लिए वैकल्पिक है।

यह हमेशा राज्य फिर एक आंशिक वर्ग में किसी भी आधार इंटरफ़ेस के लिए वैकल्पिक है:

partial class E : I3 {} 
partial class E {} 

ई की दूसरी छमाही राज्य के लिए है कि यह I3 या I2 या I1 लागू करता है की अनुमति दी है, लेकिन करने के लिए आवश्यक नहीं इसलिए।

ठीक है, मुझे मिल गया है; यह वैकल्पिक है। कोई भी अनावश्यक रूप से बेस इंटरफेस क्यों बताएगा?

शायद क्योंकि उनका मानना ​​है कि ऐसा करने से कोड को समझना आसान हो जाता है और अधिक आत्म-दस्तावेज़ीकरण होता है।

या, शायद डेवलपर

interface I1 {} 
interface I2 {} 
interface I3 : I1, I2 {} 

और महसूस किया, ओह, एक मिनट प्रतीक्षा करें, I2 I1 से विरासत के रूप में करना चाहिए कोड लिखा था।उस संपादन को क्यों बनाना चाहिए, इसके बाद डेवलपर को वापस जाने और I3 की घोषणा को बदलने के लिए में I1 का स्पष्ट उल्लेख नहीं है? मुझे अनावश्यक जानकारी को हटाने के लिए डेवलपर्स को मजबूर करने का कोई कारण नहीं दिखता है।

एक तरफ पढ़ने और समझने में आसान होने से

, वहाँ किसी भी तकनीकी आधार प्रकार सूची में स्पष्ट रूप से एक अंतरफलक बताते हुए और यह अनकहा लेकिन निहित छोड़ने के बीच का अंतर है?

आमतौर पर नहीं, लेकिन एक मामले में सूक्ष्म अंतर हो सकता है। मान लें कि आपके पास एक व्युत्पन्न कक्षा डी है जिसका बेस क्लास बी ने कुछ इंटरफेस लागू किए हैं। डी स्वचालित रूप से बी के माध्यम से उन इंटरफेस को लागू करता है। यदि आप डी की बेस क्लास सूची में इंटरफेस को दोबारा बताते हैं तो सी # कंपाइलर इंटरफेस री-कार्यान्वयन करेगा। विवरण थोड़ा सूक्ष्म हैं; यदि आप रुचि रखते हैं कि यह कैसे काम करता है तो मैं सी # 4 विनिर्देश के खंड 13.4.6 की सावधानीपूर्वक पढ़ने की सलाह देता हूं।

List<T> स्रोत कोड वास्तव में उन सभी इंटरफेस राज्य है?

सं वास्तविक स्रोत कोड है कहते हैं

public class List<T> : IList<T>, System.Collections.IList 

क्यों MSDN पूर्ण इंटरफ़ेस सूची लेकिन असली स्रोत कोड नहीं है?

क्योंकि एमएसडीएन दस्तावेज़ीकरण है; यह आपको जितना चाहें उतना अधिक जानकारी देना चाहता है। पूर्ण इंटरफ़ेस सेट क्या है यह जानने के लिए आपको दस अलग-अलग पृष्ठों के माध्यम से खोज करने के लिए दस्तावेज़ों को एक ही स्थान पर पूरा करने के लिए और अधिक स्पष्ट है।

परावर्तक पूरी सूची क्यों दिखाता है?

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

बोनस प्रश्न: क्यों IEnumerable लेकिन IList<T> से IEnumerable<T> इनहेरिट IList से विरासत नहीं है करता है?

पूर्णांक के अनुक्रम को ऑब्जेक्ट्स के अनुक्रम के रूप में माना जा सकता है, मुक्केबाजी द्वारा प्रत्येक पूर्णांक अनुक्रम से बाहर आता है। लेकिन पूर्णांक की एक पठन-लेखन सूची को ऑब्जेक्ट्स की रीड-राइट सूची के रूप में नहीं माना जा सकता है, क्योंकि आप स्ट्रिंग को ऑब्जेक्ट्स की रीड-राइट सूची में डाल सकते हैं। को IList के पूरे अनुबंध को पूरा करने की आवश्यकता नहीं है, इसलिए इससे इसका वारिस नहीं होता है।

+0

ऊपर उठाया गया। इस वर्ष बोनस प्रश्न पूछा जाता है: [[जेनेरिक IList <> गैर-जेनेरिक IList का वारिस क्यों नहीं करता है] (http://stackoverflow.com/questions/14559070/why-generic-ilist-does-not-inherit-non- जेनेरिक-इलिस्ट)] –

3
  1. हां वे करते हैं, क्योंकि List<T> में उन सभी इंटरफेस को पूरा करने के लिए गुण और विधि हो सकती है। आप नहीं जानते कि कोई इंटरफ़ेस पैरामीटर या रिटर्न वैल्यू के रूप में घोषित करने जा रहा है, इसलिए अधिक इंटरफेस सूची लागू करता है, यह अधिक बहुमुखी हो सकता है।
  2. आपका कोड संकलित होगा क्योंकि उपक्रम (var a1 = (I1)a;) रनटाइम पर विफल रहता है समय संकलित नहीं करता है। मैं var a1 = (int)a कर सकता हूं और इसे संकलित कर सकता हूं।
+0

ऐसा लगता है कि काम कर रहा है ... मैंने अंत में console.readline जोड़ा और इसे मेरे इनपुट और बिना किसी त्रुटि के समाप्त कर दिया – idm

+0

यह ठीक ठीक होगा। आपको क्या लगता है कि यह नहीं होगा? –

5

गैर-जेनेरिक इंटरफेस पिछड़े संगतता के लिए हैं। यदि आप जेनेरिक का उपयोग करके कोड लिखते हैं और अपनी सूची को .NET 1.0 (जिसमें जेनेरिक नहीं है) में लिखे गए कुछ मॉड्यूल में पास करना चाहते हैं, तो भी आप इसे सफल होने के लिए चाहते हैं। इसलिए IList, ICollection, IEnumerable

2

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

5

एरिक लिपर्ट से महान प्रश्न और महान उत्तर। यह प्रश्न अतीत में मेरे दिमाग में आया, और निम्नलिखित मेरी समझ है, उम्मीद है कि यह आपकी मदद करेगी।

मान लीजिए कि मैं इस ग्रह में ब्रह्मांड में किसी अन्य ग्रह में सी # प्रोग्रामर हूं, सभी जानवर उड़ सकते हैं।,

interface IFlyable 
{ 
    void Fly(); 
} 
interface IAnimal : IFlyable 
{ 
    //something 
} 
interface IBird : IAnimal, IFlyable 
{ 
} 

वैसे आप भ्रमित हो सकता है के बाद से BirdsAnimals हैं, और सभी Animals उड़ सकता है, हम क्यों इंटरफेस IBird में IFlyable निर्दिष्ट करने की आवश्यकता है: तो मेरा कार्यक्रम की तरह दिखता है? ठीक है इसे इसे बदल दें:

interface IBird : IAnimal 
{ 
} 

मुझे 100% यकीन है कि कार्यक्रम पहले की तरह काम करता है, इसलिए कुछ भी नहीं बदला गया है? इंटरफ़ेस IBird में IFlyable पूरी तरह से बेकार है? चलो आगे बढ़ें।

एक दिन, मेरी कंपनी ने पृथ्वी पर दूसरी कंपनी को सॉफ्टवेयर बेचा। लेकिन पृथ्वी पर, सभी जानवर उड़ नहीं सकते! तो निश्चित रूप से, हमें इंटरफ़ेस IAnimal और इसे लागू करने वाले वर्गों को संशोधित करने की आवश्यकता है। संशोधन के बाद, मैंने पाया कि IBird अब गलत है क्योंकि पृथ्वी के पक्षी उड़ सकते हैं! अब मुझे से IFlyable हटाने का अफसोस है!

+0

एर ... फ्लाई –

+0

के लिए +1 यह छोड़कर कि एरिक का जवाब कहता है कि _source code_ वास्तव में केवल आईबीर्ड के बराबर है: IAnimal, और IFlyable केवल एमएसडीएन, आईएलएसपी, आदि में अतिरिक्त के रूप में दिखाई देता है (अनुमानित) आपकी मदद करने के लिए जानकारी। –

+0

लेकिन फिर आपको अन्य सभी इंटरफेस 'आईडीओजी', 'आईसीएटी',' आईरिनोसेरोस 'इत्यादि से गुजरना है, जिसे आपने संभवतः अपने हर-पशु-मक्खियों के ब्रह्मांड में' IFlyable 'भी जोड़ा है, और * हटाएं * IFlyable से उन्हें। किसी भी तरह से, आपके पास करने के लिए बहुत सारे अपडेट हैं। – Blorgbeard

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