'IList' बनाम 'ICollection' बनाम 'Collection' की वापसी


119

मैं इस बात को लेकर उलझन में हूं कि मुझे किस प्रकार के संग्रह को अपने सार्वजनिक एपीआई तरीकों और गुणों से वापस करना चाहिए।

मेरे पास जो संग्रह हैं IList, वे हैं , ICollectionऔर Collection

क्या इन प्रकारों में से एक को हमेशा दूसरों पर पसंद किया जाता है, या क्या यह विशिष्ट स्थिति पर निर्भर करता है?


4
डुप्लिकेट: stackoverflow.com/questions/271710/…
रॉबी

जवाबों:


71

आम तौर पर आपको एक प्रकार वापस करना चाहिए जो यथासंभव सामान्य है, यानी एक वह जो केवल पर्याप्त डेटा को जानता है जिसे उपभोक्ता को उपयोग करने की आवश्यकता है। इस तरह से आपको एपीआई के कार्यान्वयन को बदलने की अधिक स्वतंत्रता है, जो उस कोड का उपयोग किए बिना उसे तोड़ रहा है।

IEnumerable<T>वापसी प्रकार के रूप में भी इंटरफ़ेस पर विचार करें । यदि परिणाम केवल पुनरावृत्त होने जा रहा है, तो उपभोक्ता को इससे अधिक की आवश्यकता नहीं है।


25
लेकिन यह भी विचार करें कि ICollection <T> जो IEnumerable <T> का विस्तार करता है, एक गणना संपत्ति सहित अतिरिक्त उपयोगिताओं को प्रदान करने के लिए। यह मददगार हो सकता है क्योंकि आप कई बार अनुक्रम को ट्रेस किए बिना अनुक्रम की लंबाई निर्धारित कर सकते हैं।
15

11
@retrodrone: वास्तव में Countविधि का कार्यान्वयन संग्रह के वास्तविक प्रकार की जाँच करता है, इसलिए यह कुछ ज्ञात प्रकारों जैसे सरणियों के लिए Lengthया Countगुणों का उपयोग करेगा और ICollectionतब भी जब आप इसे एक के रूप में आपूर्ति करेंगे IEnumerable
गुफ़ा

8
@Guffa: यह टिप्पणी करना श्रेयस्कर होगा कि अगर एक वर्ग Thing<T>लागू IList<T>नहीं बल्कि गैर सामान्य ICollectionहै, तो बुला IEnumerable<Cat>.Count()एक पर Thing<Cat>तेजी से होगा, लेकिन बुला IEnumerable<Animal>.Count()धीमी गति से होगा (के बाद से विस्तार विधि के लिए विचार करेंगे, और नहीं मिल रहा, के एक कार्यान्वयन ICollection<Cat>)। यदि वर्ग गैर-जेनेरिक को लागू करता है ICollection, हालांकि, IEnumerable<Animal>.Countवह ढूंढेगा और उसका उपयोग करेगा।
सुपरकैट


8
मैं असहमत हूं। आपके पास जो सबसे अमीर प्रकार है उसे वापस करना सबसे अच्छा है ताकि ग्राहक इसे सीधे उपयोग कर सकें यदि वे चाहते हैं। यदि आपके पास एक सूची <> है, तो केवल कॉल करने के लिए मजबूर करने के लिए एक आईयूनेरेबल <> क्यों लौटाएं?
zumalifeguard

140

ICollection<T>एक अंतरफलक है कि इस तरह के रूप में संग्रह अर्थ विज्ञान को उजागर करता है Add(), Remove()और Count

Collection<T>ICollection<T>इंटरफ़ेस का एक ठोस कार्यान्वयन है ।

IList<T>अनिवार्य रूप ICollection<T>से यादृच्छिक क्रम-आधारित पहुंच के साथ है।

इस मामले में आपको यह तय करना चाहिए कि आपके परिणामों को सूची आधारित शब्दार्थ की आवश्यकता है जैसे कि आदेश आधारित अनुक्रमण (तब उपयोग करें IList<T>) या क्या आपको परिणामों के अनियंत्रित "बैग" को वापस करने की आवश्यकता है या नहीं (तब उपयोग करें ICollection<T>)।


5
Collection<T>लागू करता है IList<T>और न केवल ICollection<T>
कोडइन्कॉउंस

56
.Net में सभी संग्रह आदेश दिए गए हैं, क्योंकि IEnumerable<T>आदेश दिया गया है। क्या अलग IList<T>से ICollection<T>है कि यह अनुक्रमित के साथ काम करने के लिए सदस्यों को प्रदान करता है। उदाहरण के लिए list[5]काम करता है, लेकिन collection[5]संकलन नहीं करेगा।
स्विक

5
मैं यह भी असहमत हूं कि संग्रह का आदेश दिया जाना चाहिए IList<T>। बहुत सारे ऑर्डर किए गए संग्रह हैं जो नहीं करते हैं। IList<T>तेजी से अनुक्रमित पहुंच के बारे में है।
कोडइन्चोस

4
@yoyo .net संग्रह कक्षाएं और इंटरफेस बस बुरी तरह से डिज़ाइन किए गए हैं और बुरी तरह से नामित हैं। मैं इस बारे में ज्यादा नहीं सोचूंगा कि उन्होंने उनका नाम ऐसा क्यों रखा।
कोडइन्चोस

6
@vvick: क्या सभी संग्रह आदेश IEnumerable<T>दिए गए हैं? ले HashSet<T>- यह लागू होता है, IEnumerable<T>लेकिन स्पष्ट रूप से आदेश नहीं दिया गया है। यानी आपके पास वस्तुओं के आदेश पर कोई प्रभाव नहीं है और यह आदेश किसी भी समय बदल सकता है, अगर आंतरिक हैश तालिका फिर से व्यवस्थित हो।
ओलिवियर जैकोट-डेसकॉम्बस

61

के बीच मुख्य अंतर है IList<T>और ICollection<T>यह IList<T>आपको एक सूचकांक के माध्यम से तत्वों का उपयोग करने की अनुमति देता है। IList<T>सरणी-प्रकार के प्रकारों का वर्णन करता है। एक में तत्व ICollection<T>केवल गणना के माध्यम से पहुँचा जा सकता है। दोनों तत्वों के सम्मिलन और विलोपन की अनुमति देते हैं।

यदि आपको केवल एक संग्रह की गणना करने की आवश्यकता है, तो IEnumerable<T>पसंद किया जाना है। दूसरों पर इसके दो फायदे हैं:

  1. यह संग्रह में परिवर्तन को अस्वीकार करता है (लेकिन तत्वों के लिए नहीं, यदि वे संदर्भ प्रकार के हैं)।

  2. यह उन स्रोतों की सबसे बड़ी संभव विविधता की अनुमति देता है, जिसमें गणनाएं शामिल हैं जो एल्गोरिदम से उत्पन्न होती हैं और संग्रह बिल्कुल नहीं होती हैं।

Collection<T>एक बेस क्लास है जो मुख्य रूप से संग्रहकर्ताओं के कार्यान्वयन के लिए उपयोगी है। यदि आप इसे इंटरफेस (एपीआई) में उजागर करते हैं, तो इससे प्राप्त होने वाले कई उपयोगी संग्रह को बाहर नहीं किया जाएगा।


इसका एक नुकसान IList<T>यह है कि सरणियाँ इसे लागू करती हैं लेकिन आपको आइटम जोड़ने या निकालने की अनुमति नहीं देती हैं (अर्थात आप सरणी की लंबाई नहीं बदल सकते हैं)। यदि आप IList<T>.Add(item)किसी सरणी पर कॉल करते हैं, तो एक अपवाद फेंक दिया जाएगा । स्थिति कुछ हद तक बदली हुई है क्योंकि IList<T>एक बूलियन संपत्ति है IsReadOnlyजिसे आप ऐसा करने का प्रयास करने से पहले जांच सकते हैं। लेकिन मेरी नजर में, यह अभी भी पुस्तकालय में एक डिजाइन दोष है । इसलिए, मैं List<T>सीधे उपयोग करता हूं , जब वस्तुओं को जोड़ने या हटाने की संभावना की आवश्यकता होती है।


कोड विश्लेषण (और FxCop) की सलाह है कि जब एक ठोस सामान्य संग्रह लौटने निम्न में से एक वापस आ जाना चाहिए: Collection, ReadOnlyCollectionया KeyedCollection। और वह Listवापस नहीं किया जाना चाहिए।
डेविड आरआर

@ डैविड्रआर: अक्सर यह एक सूची को एक विधि से पारित करने के लिए उपयोगी है जिसमें आइटम जोड़ना या निकालना है। यदि आप पैरामीटर को टाइप करते हैं IList<T>, तो यह सुनिश्चित करने का कोई तरीका नहीं है कि विधि को सरणी के रूप में पैरामीटर के रूप में नहीं बुलाया जाएगा।
ओलिवियर जैकोट-डेसकॉम्बस

7

IList<T>सभी सामान्य सूचियों के लिए आधार इंटरफ़ेस है। चूँकि यह एक आदेशित संग्रह है, कार्यान्वयन क्रमबद्धता क्रम से सम्मिलन क्रम तक लेकर निर्णय कर सकता है। इसके अलावा Ilistआइटम की संपत्ति है कि तरीकों को उनके सूचकांक के आधार पर सूची में प्रविष्टियों को पढ़ने और संपादित करने की अनुमति देता है। यह स्थिति सूचकांक में सूची से मूल्य को सम्मिलित / दूर करने के लिए संभव बनाता है।

इसके अलावा IList<T> : ICollection<T>, ICollection<T>कार्यान्वयन के लिए यहां से सभी विधियां भी उपलब्ध हैं।

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

Collection<T>के लिए एक कार्यान्वयन प्रदान करता है IList<T>, IListऔर IReadOnlyList<T>

यदि आप ICollection<T>इसके बजाय एक संकरा इंटरफ़ेस प्रकार का उपयोग करते हैं IList<T>, तो आप अपने कोड को टूटने वाले परिवर्तनों से बचाते हैं। यदि आप एक व्यापक इंटरफ़ेस प्रकार का उपयोग करते हैं जैसे कि IList<T>, आपको कोड परिवर्तन टूटने का खतरा अधिक है।

एक स्रोत से उद्धरण ,

ICollection, ICollection<T>: आप या संग्रह संशोधित करना चाहते हैं तो आप अपने आकार के बारे में परवाह। IList, IList<T>: आप संग्रह संशोधित करना चाहते हैं और आप आदेश और / या संग्रह में तत्वों की स्थिति के बारे में परवाह है।


5

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

और, यदि आपने इसे पहले नहीं पढ़ा है, तो ब्रैड अब्राम्स और क्रिज़स्टॉफ़ सेलिना ने "फ्रेमवर्क डिज़ाइन दिशानिर्देश: कन्वेंशन, मुहावरे और पुन: प्रयोज्य .NET पुस्तकालयों के लिए पैटर्न" नामक एक महान पुस्तक लिखी (आप यहां से एक पाचन डाउनलोड कर सकते हैं )।


IEnumerable<T>केवल पढ़ा जाता है? निश्चित रूप से, लेकिन जब इसे रिपॉजिटरी के संदर्भ में वापस लिया जाता है, तब भी जब टॉलिस्ट को निष्पादित करना थ्रेड सुरक्षित नहीं होता है। समस्या तब है जब मूल डेटा स्रोत जीसी मिलता है तो IEnumarble.ToList () बहु थ्रेडेड संदर्भ में काम नहीं करता है। यह एक रैखिक एक पर काम करता है क्योंकि आप काम करने के बाद जीसी कहते हैं, लेकिन asyncअब 4.5+ IEnumarbale में एक दिन का उपयोग करने से एक गेंद दर्द हो रहा है।
पायोतर कुला

-3

कुछ ऐसे विषय हैं जो इस प्रश्न से आते हैं:

  • वर्गों बनाम इंटरफेस
  • कई विशिष्ट वर्गों, संग्रह, सूची, सरणी से कौन सा विशिष्ट वर्ग?
  • आम कक्षाएं बनाम सबमिट ("जेनरिक") संग्रह

आप इसके ऑब्जेक्ट ओरिएंटेड एपीआई पर प्रकाश डालना चाह सकते हैं

वर्गों बनाम इंटरफेस

यदि आपके पास इंटरफेस के साथ बहुत अनुभव नहीं है, तो मैं कक्षाओं के लिए छड़ी की सलाह देता हूं। मैं कई बार डेवलपर्स को इंटरफेस में कूदते हुए देखता हूं, भले ही वह नॉटिलरिली न हो।

और, अंत में, एक अच्छे क्लास डिज़ाइन के बजाय, एक खराब इंटरफ़ेस डिज़ाइन कर रहा है, जो कि, अंत में, एक अच्छे इंटरफ़ेस डिज़ाइन के लिए माइग्रेट किया जा सकता है ...

यदि आपको इसकी आवश्यकता नहीं है, तो आपको एपीआई में बहुत सारे इंटरफेस दिखाई देंगे, लेकिन, जल्दी मत करो।

आप अंततः सीखेंगे कि अपने कोड में इंटरफेस कैसे लागू करें।

कई विशिष्ट वर्गों, संग्रह, सूची, सरणी से कौन सा विशिष्ट वर्ग?

C # (डॉटनेट) में कई कक्षाएं हैं जिन्हें आपस में जोड़ा जा सकता है। जैसा कि पहले ही उल्लेख किया गया है, यदि आपको अधिक विशिष्ट वर्ग से कुछ चाहिए, जैसे कि "कैनबर्सोल्डक्लास", तो इसे अपने एपीआई में स्पष्ट करें।

क्या आपके एपीआई उपयोगकर्ता को वास्तव में यह जानने की जरूरत है कि आपकी कक्षा को हल किया जा सकता है, या तत्वों के लिए कुछ प्रारूप लागू किया जा सकता है? फिर "CanBeSreadClass" या "ElementsCanBePaintedClass" का उपयोग करें, अन्यथा "GenericBrandClass" का उपयोग करें।

अन्यथा, अधिक सामान्य वर्ग का उपयोग करें।

सामान्य संग्रह कक्षाएं बनाम सबमिट ("जेनरिक") संग्रह

आप पाएंगे कि ऐसी कक्षाएं हैं जिनमें अन्य तत्व शामिल हैं, और आप यह निर्दिष्ट कर सकते हैं कि सभी तत्व एक विशिष्ट प्रकार के होने चाहिए।

जेनेरिक कलेक्शंस वे क्लासेस हैं जिन्हें आप एक ही संग्रह का उपयोग कर सकते हैं, कई कोड एप्लिकेशन के लिए, एक नया संग्रह बनाने के लिए, प्रत्येक नए सबमिट प्रकार के लिए, जैसे: संग्रह

क्या आपके API उपयोगकर्ता को सभी तत्वों के लिए एक ही विशिष्ट प्रकार की आवश्यकता है?

जैसे कुछ का उपयोग करें List<WashingtonApple>

क्या आपके एपीआई उपयोगकर्ता को कई संबंधित प्रकारों की आवश्यकता है?

List<Fruit>अपने एपीआई के लिए बेनकाब , और उपयोग List<Orange> List<Banana>, List<Strawberry>आंतरिक रूप से, जहां Orange, Bananaऔर Strawberryसे वंशज हैं Fruit

क्या आपके एपीआई उपयोगकर्ता को एक सामान्य प्रकार के संग्रह की आवश्यकता है?

उपयोग List, जहां सभी आइटम हैं object

चीयर्स।


7
"यदि आपके पास इंटरफेस के साथ बहुत अनुभव नहीं है, तो मैं कक्षाओं के लिए छड़ी की सलाह देता हूं" यह अच्छी सलाह नहीं है। यह कहने जैसा है कि अगर कोई ऐसी चीज है जिसे आप नहीं जानते हैं, तो उससे दूर रहें। इंटरफेस बेहद शक्तिशाली हैं और "प्रोग्राम टू एब्स्ट्रैक्ट बनाम कंसट्रक्शन" की अवधारणा का समर्थन करते हैं। वे मॉक के माध्यम से टाइप इंटरचेंज करने की क्षमता के कारण यूनिट टेस्टिंग करने के लिए भी काफी शक्तिशाली हैं। इन टिप्पणियों से परे इंटरफेस का उपयोग करने के लिए अन्य महान कारणों का एक गुच्छा है, इसलिए कृपया सभी तरीकों से उनका अन्वेषण करें।
atconway

@atconway मैं नियामक इंटरफेस का उपयोग करता है, लेकिन, कई अवधारणाओं के रूप में, एक शक्तिशाली उपकरण, यह मिश्रण-उपयोग के लिए आसान हो सकता है। और, कभी-कभी, डेवलपर को इसकी आवश्यकता नहीं हो सकती है। मेरा सुझाव "कभी हस्तक्षेप न करें" था, मेरा सुझाव था "इस मामले में, आप इंटरफेस को छोड़ सकते हैं। इसके बारे में जानें, और आप उनमें से सबसे अच्छा पा सकते हैं, बाद में"। चीयर्स।
umlcat

1
मैं हमेशा इंटरफ़ेस के लिए प्रोग्रामिंग करने की सलाह देता हूं। यह कोड को शिथिल युग्मित रखने में मदद करता है।
mac10688

@ mac10688 मेरा पिछला जवाब (atconway) आपकी टिप्पणी पर भी लागू होता है।
umlcat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.