क्यों सरणी IList लागू करता है?


141

System.Array वर्ग की परिभाषा देखें

public abstract class Array : IList, ...

सैद्धांतिक रूप से, मुझे यह लिखने में सक्षम होना चाहिए और खुश रहना चाहिए

int[] list = new int[] {};
IList iList = (IList)list;

मुझे आईलिस्ट से किसी भी विधि को कॉल करने में सक्षम होना चाहिए

 ilist.Add(1); //exception here

मेरा सवाल यह नहीं है कि मुझे अपवाद क्यों मिला, बल्कि एरे आईलिस्ट को लागू क्यों करता है ?


22
अच्छा सवाल है। मुझे वसा इंटरफेस का विचार पसंद नहीं आया (यह इस तरह के डिजाइन के लिए तकनीकी शब्द है)।
कोनराड रुडोल्फ


2
क्या कोई वास्तव में एलएसपी के बारे में परवाह करता है? यह मुझे काफी अकादमिक लगता है।
गाबे

13
@ Gabe, तो आपको बड़े कोडबेस के साथ काम करने की आवश्यकता है। एक व्यवहार (एक इंटरफ़ेस से विरासत में) को लागू करना और फिर उन चीजों को अनदेखा करना जो आपको पसंद नहीं हैं / समर्थन नहीं कर सकते बदबूदार, बाधित, कास्टिंग और अंत में: छोटी गाड़ी कोड।
मारियस

3
@Gabe इसका संग्रह जो उत्परिवर्तन को समाहित करता है न कि इसमें निहित संस्थाएँ। आप अपने वर्ग के सदस्य को एक प्रकार का बना सकते हैं जो IRWList <> और IReadList <> दोनों को लागू करता है, यदि आपके वर्ग में IRWList <> आंतरिक रूप से उपयोग करता है और इसे IReadList के रूप में उजागर करता है। हाँ, आप जटिलता कहीं डाल करने के लिए है, लेकिन मैं अभी नहीं दिख रहा है कि कैसे LSP एक बहुत अच्छा डिजाइन सिद्धांत के रूप में अनदेखी पर लागू होने वाला (IsReadOnly संपत्ति हालांकि जो एक उपभोक्ताओं के दृष्टिकोण से IList और अधिक जटिल बना देता है के बारे में पता नहीं था)
मेरियस

जवाबों:


94

क्योंकि एक सरणी अनुक्रमणिका द्वारा तेजी से पहुंच की अनुमति देता है, और IList/ IList<T>यह एकमात्र संग्रह इंटरफेस है जो इसका समर्थन करता है। तो शायद आपका असली सवाल है "इंडेक्सर्स के साथ लगातार संग्रह के लिए कोई इंटरफ़ेस क्यों है?" और इसका मेरे पास कोई जवाब नहीं है।

संग्रह के लिए आसानी से कोई इंटरफेस नहीं हैं। और मैं अनुक्रमणिका इंटरफ़ेस के साथ एक निरंतर आकार से भी अधिक उन्हें याद कर रहा हूं।

IMO में संग्रह की विशेषताओं के आधार पर कई और (सामान्य) संग्रह इंटरफेस होने चाहिए। और नाम भी अलग-अलग होने चाहिए थे, Listक्योंकि एक इंडेक्सर के साथ कुछ वास्तव में बेवकूफ आईएमओ है।

  • सिर्फ एन्यूमरेशन IEnumerable<T>
  • Readonly लेकिन कोई अनुक्रमणिका (.Count, .Contains, ...)
  • आकार बदलने योग्य, लेकिन कोई अनुक्रमणिका नहीं, जैसे (जोड़ें, निकालें, ...) वर्तमान ICollection<T>
  • अनुक्रमणिका (अनुक्रमणिका, अनुक्रमणिका, ...) के साथ पढ़ें
  • अनुक्रमणिका के साथ लगातार आकार (एक सेटर के साथ अनुक्रमणिका)
  • अनुक्रमणिका के साथ चर आकार (डालें, ...) वर्तमान IList<T>

मुझे लगता है कि वर्तमान संग्रह इंटरफेस खराब डिजाइन हैं। लेकिन चूंकि उनके पास आपको यह बताने का गुण है कि कौन से तरीके मान्य हैं (और यह इन तरीकों के अनुबंध का हिस्सा है) यह प्रतिस्थापन सिद्धांत को नहीं तोड़ता है।


14
जवाब के लिए धन्यवाद। लेकिन मैं इस सवाल को छोड़ देता हूं। वजह साफ है। इंटरफ़ेस एक सार्वजनिक अनुबंध है। यदि कोई इसे लागू करता है, तो सभी सदस्यों को पूरी तरह से लागू करना चाहिए, अन्यथा यह एलएसपी को तोड़ देता है और आम तौर पर खराब हो जाता है, क्या यह नहीं है?
oleksii

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

2
@smelch मुझे खेद है लेकिन आपको LSP गलत लगा। एक सरणी लागू नहीं होती है addऔर इस तरह उस चीज के लिए प्रतिस्थापित नहीं किया जा सकता है जो उस क्षमता की आवश्यकता होती है।
रुण FS

7
मैंने स्वीकार किया कि यह तकनीकी रूप से केवल एलएसपी का उल्लंघन नहीं करता है क्योंकि दस्तावेज में कहा गया है कि आपको IsFixedSizeऔर IsReadOnlyगुणों की जांच करनी चाहिए , यह निश्चित रूप से टेल, डोन्ट आस्क सिद्धांत और सिद्धांत का उल्लंघन नहीं करता है । जब आप 9 तरीकों में से 4 के लिए अपवादों को फेंकने जा रहे हैं तो एक इंटरफ़ेस क्यों लागू करें?
मैथ्यू

11
मूल प्रश्न के कुछ समय बीत चुका है। लेकिन अब .Net 4.5 के साथ, अतिरिक्त इंटरफेस IReadOnlyList और IReadOnlyCollection हैं
तोबिस

43

कहने के लिए दस्तावेज़ीकरण की टिप्पणी अनुभागIList

IList ICollection इंटरफ़ेस का एक वंशज है और सभी गैर-सामान्य सूचियों का आधार इंटरफ़ेस है। IList कार्यान्वयन तीन श्रेणियों में आते हैं: केवल पढ़ने के लिए, निश्चित-आकार और परिवर्तनशील आकार में । केवल पढ़ने के लिए IList को संशोधित नहीं किया जा सकता है। एक निश्चित आकार का IList तत्वों को जोड़ने या हटाने की अनुमति नहीं देता है, लेकिन यह मौजूदा तत्वों के संशोधन की अनुमति देता है। एक चर-आकार IList तत्वों को जोड़ने, हटाने और संशोधित करने की अनुमति देता है।

स्पष्ट रूप से सरणियाँ निश्चित-आकार की श्रेणी में आती हैं, इसलिए इंटरफ़ेस के बचाव से यह समझ में आता है।


4
मुझे लगता है कि वे बहुत सारे इंटरफेस के साथ समाप्त हो गए होंगे। IListFixedSize, IListReadOnly ...
मैग्नस

9
यह वास्तव में प्रलेखन के दृष्टिकोण से एक अच्छा जवाब है। लेकिन मेरे लिए यह एक हैक की तरह दिखता है। सभी सदस्यों को लागू करने के लिए एक वर्ग के लिए इंटरफेस को पतला और सरल होना चाहिए।
ओलेक्सी

1
@oleksii: मैं सहमत हूं। इंटरफेस और रनटाइम अपवाद सबसे सुरुचिपूर्ण संयोजन नहीं हैं। इसके बचाव में Arrayयह Addविधि स्पष्ट रूप से लागू होती है , जो इसे दुर्घटना से कॉल करने के जोखिम को कम करती है।
ब्रायन रासमुसेन

जब तक हम IListउस कार्यान्वयन को नहीं बनाते हैं, संशोधन और परिवर्धन / निष्कासन दोनों को रोक देता है । फिर दस्तावेज़ सही नहीं हैं। : पी
टिमो

1
@ मैग्नस - इन .नेट 4.5, में अतिरिक्त इंटरफेस IReadOnlyList और IReadOnlyCollection हैं
RBT

17

क्योंकि सभी ILists उत्परिवर्तित नहीं होते हैं (देखें IList.IsFixedSizeऔर IList.IsReadOnly), और सरणियाँ निश्चित आकार की सूचियों की तरह व्यवहार करती हैं।

यदि आपका प्रश्न वास्तव में " गैर-जेनेरिक इंटरफ़ेस को क्यों लागू करता है ", तो इसका उत्तर यह है कि जेनरिक के साथ आने से पहले ये आसपास थे।


10
@oleksii: नहीं, यह एलएसपी को नहीं तोड़ता, क्योंकि इंटरफ़ेस IList ही आपको बताता है कि यह परस्पर नहीं हो सकता है। यदि यह वास्तव में परिवर्तनशील होने की गारंटी थी और सरणी ने आपको अन्यथा बताया था, तो यह नियम को तोड़ देगा।
user541686

असल में, एरिक जेनेरिक के मामले में एलएसपी को तोड़ता है IList<T>और गैर-जेनेरिक के मामले में इसे नहीं तोड़ता है IList: enterprisecraftsmanship.com/2014/11/22/…
व्लादिमीर

5

यह एक विरासत है जो हमारे पास उस समय से है जब यह स्पष्ट नहीं था कि केवल संग्रह को कैसे पढ़ा जाए और Array को केवल पढ़ा जाए या नहीं। IList इंटरफ़ेस में IsFixedSize और IsReadOnly झंडे हैं। IsReadOnly ध्वज का मतलब है कि संग्रह को बिल्कुल नहीं बदला जा सकता है और IsFixedSize का अर्थ है कि संग्रह संशोधन की अनुमति देता है, लेकिन वस्तुओं को जोड़ना या निकालना नहीं है।

नेट 4.5 के समय यह स्पष्ट था कि कुछ "मध्यवर्ती" इंटरफेस केवल पढ़ने के संग्रह के साथ काम करने की आवश्यकता है, तो IReadOnlyCollection<T>और IReadOnlyList<T>शुरू किए गए थे।

यहां विवरणों का वर्णन करने वाला एक शानदार ब्लॉग पोस्ट है: केवल .NET में संग्रह पढ़ें


0

IList इंटरफ़ेस की परिभाषा "वस्तुओं के एक गैर-सामान्य संग्रह का प्रतिनिधित्व करती है जिसे इंडेक्स द्वारा व्यक्तिगत रूप से एक्सेस किया जा सकता है।" सरणी इस परिभाषा को पूरी तरह से संतुष्ट करती है, इसलिए इंटरफ़ेस को लागू करना चाहिए। ऐड () विधि कहते समय अपवाद "System.NotSupportedException: संग्रह एक निश्चित आकार का था" और हुआ क्योंकि सरणी गतिशील रूप से अपनी क्षमता नहीं बढ़ा सकती है। सरणी वस्तु के निर्माण के दौरान इसकी क्षमता को परिभाषित किया गया है।


0

एक सरणी लागू करने के बाद IList (और संक्रमणीय रूप से, ICollection) ने Linq2Objects इंजन को सरल बना दिया है, क्योंकि IEnumerable को IList / ICollection में कास्टिंग करने पर भी सरणियों के लिए काम किया जाएगा।

उदाहरण के लिए, एक गणना () Array.Length को अंडर-द-हुड कहते हुए समाप्त होती है, क्योंकि यह ICollection के लिए डाली गई है और सरणी का कार्यान्वयन लंबाई देता है।

इसके बिना, Linq2Objects इंजन में सरणियों के लिए विशेष उपचार नहीं होगा और बुरी तरह से प्रदर्शन किया जाएगा, या उन्हें कोड के लिए विशेष-केस उपचार को जोड़ने के लिए कोड को दोगुना करने की आवश्यकता होगी (जैसे वे IList के लिए करते हैं)। उन्होंने इसके बजाय सरणी कार्यान्वयन IList लागू करने का विकल्प चुना है।

यही मेरा "क्यों" पर है।


0

इसके अलावा कार्यान्वयन विवरण LINQ IList के लिए अंतिम चेक, यदि यह सूची लागू नहीं करता है तो उन्हें 2 अंतिम चेकों की आवश्यकता होगी जो सभी अंतिम कॉल को धीमा कर रहे हैं या O (N) लेने वाले Array पर अंतिम हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.