सूची <T> या IList <T> [बंद]


495

क्या कोई मुझे समझा सकता है कि मैं C # पर IList over List का उपयोग क्यों करना चाहूंगा?

संबंधित प्रश्न: क्यों उजागर करना बुरा माना जाता हैList<T>


1
"एक इंटरफ़ेस के लिए कोड एक कार्यान्वयन नहीं" के लिए इंटरनेट खोज और आप पूरे दिन पढ़ सकते हैं..और कुछ h0ly युद्ध पाते हैं।
ग्रेनडाकर

जवाबों:


446

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

यदि आप इसे आंतरिक रूप से उपयोग कर रहे हैं, तो आप इतना ध्यान नहीं दे सकते हैं, और उपयोग List<T>करना ठीक हो सकता है।


19
मैं (सूक्ष्म) अंतर नहीं समझ रहा हूँ, क्या कोई उदाहरण है जो आप मुझे बता सकते हैं?
स्टिंगजैक

134
कहते हैं कि आपने मूल रूप से सूची <T> का उपयोग किया था और एक विशेष CaseInsensitiveList <T> का उपयोग करना चाहते थे, जो दोनों IList <T> को लागू करते हैं। यदि आप ठोस प्रकार का उपयोग करते हैं तो सभी कॉलर्स को अपडेट करने की आवश्यकता है। यदि IList <T> के रूप में उजागर किया जाता है, तो कॉलर को बदलना नहीं पड़ता है।
तवान्फोसन

46
आह। ठीक। मै समझ गया। एक अनुबंध के लिए सबसे कम आम भाजक उठा। धन्यवाद!
स्टिंगजैक

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

14
यह भी ध्यान दें कि टी []: IList <T>, ताकि प्रदर्शन कारणों से आप हमेशा अपनी सूची से सूची <T> को वापस करने की अदला-बदली कर सकते हैं और अपनी प्रक्रिया को T [] लौटा सकते हैं, और यदि प्रक्रिया को IList <T> वापस करने की घोषणा की जाती है। (या शायद ICollection <T>, या IEnumerable <T>) और कुछ नहीं बदलना होगा।
yfeldblum

322

कम लोकप्रिय जवाब प्रोग्रामर है जैसे अपने सॉफ्टवेयर का ढोंग करना दुनिया भर में फिर से इस्तेमाल किया जा रहा है, जब परियोजनाओं के बहुमत को बनाए रखना बहुत कम लोगों द्वारा बनाए रखा जाएगा और हालांकि अच्छा इंटरफ़ेस-संबंधित साउंडबाइट हैं, तो आप बहक रहे हैं स्वयं।

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

सॉफ्टवेयर अंतरिक्ष यात्री

जाहिर है अगर आपसे पूछा जा रहा है कि आप एक साक्षात्कार में किसका उपयोग करते हैं, तो आप कहते हैं कि आइलिस्ट, मुस्कुराओ, और दोनों अपने आप को बहुत चालाक होने के लिए प्रसन्न दिखते हैं। या एपीआई, IList का सामना करने वाली जनता के लिए। उम्मीद है कि आपको मेरी बात सही लगेगी।


65
मुझे आपके व्यंग्यात्मक उत्तर से असहमत होना पड़ेगा। मैं अति-वास्तुकला की भावना से पूरी तरह असहमत नहीं हूं क्योंकि यह एक वास्तविक समस्या है। हालांकि मुझे लगता है कि विशेष रूप से संग्रह के मामले में जो इंटरफेस वास्तव में चमकते हैं। मान लें कि मेरे पास एक फ़ंक्शन है जो फ़ंक्शन के IEnumerable<string>अंदर है, मैं List<string>अपने संग्रह को उत्पन्न करने के लिए आंतरिक बैकिंग स्टोर के लिए उपयोग कर सकता हूं, लेकिन मैं केवल कॉलर्स को यह बताना चाहता हूं कि यह सामग्री है, न कि जोड़ना या निकालना। एक पैरामीटर के रूप में एक इंटरफ़ेस को स्वीकार करना एक समान संदेश का संचार करता है "मुझे स्ट्रिंग्स के संग्रह की आवश्यकता है, हालांकि चिंता न करें, मैं इसे नहीं बदलूंगा।"
जॉस्पररी

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

48
किसी को इस Arec कहना था ... भले ही आप एक परिणाम के रूप में नफरत मेल का पीछा करते हुए शैक्षिक पैटर्न के सभी प्रकार मिल गया है। हम सभी के लिए +1 जो एक छोटी सी ऐप को इंटरफेस से लोड करने और "फ़ाइंड डेफिनिशन" पर क्लिक करने पर हमसे नफरत करता है, हमें समस्या के स्रोत के अलावा कहीं और ले जाता है ... क्या मैं "आर्किटेक्चर एस्ट्रोनॉट्स" वाक्यांश उधार ले सकता हूं? मैं देख सकता हूं कि यह काम आएगा।
Gats

6
यदि यह संभव होगा, तो मैं आपको इस उत्तर के लिए 1000 अंक दूंगा। : डी
शमूएल

8
मैं पैटर्न पीछा करने के व्यापक परिणाम के बारे में बात कर रहा था। आम इंटरफेस के लिए इंटरफेस एक पैटर्न का पीछा करते हुए अच्छा, अतिरिक्त परतों के लिए, खराब।
Gats

186

इंटरफ़ेस एक वादा (या एक अनुबंध) है।

जैसा कि यह हमेशा वादों के साथ होता है - बेहतर से छोटा


56
हमेशा बेहतर नहीं, बस रखने के लिए आसान! :)
कर्क ब्रॉडहर्स्ट

5
मुझे यह नहीं मिला। तो IListवादा है। यहां कौन सा छोटा और बेहतर वादा है? यह तर्कसंगत नहीं है।
नवफाल

3
किसी अन्य वर्ग के लिए मैं सहमत हूँ। लेकिन नहीं List<T>, क्योंकि AddRangeइंटरफ़ेस पर परिभाषित नहीं किया गया है।
जेसी डे विट

3
यह वास्तव में इस विशेष मामले में मददगार नहीं है। सबसे अच्छा वादा वही है जो रखा जाता है। IList<T>वादा करता है कि यह नहीं रख सकता है। उदाहरण के लिए, वहाँ एक Addविधि से फेंक सकता है अगर IList<T>केवल पढ़ने के लिए होता है। List<T>दूसरी ओर हमेशा लिखने योग्य होता है और इस प्रकार हमेशा अपने वादे करता रहता है। इसके अलावा, .NET 4.6 के बाद से, अब हमारे पास है IReadOnlyCollection<T>और IReadOnlyList<T>जो लगभग हमेशा से बेहतर हैं IList<T>। और वे सहसंयोजक हैं। बचो IList<T>!
ZunTzu

@ZunTzu मैं तर्क दूंगा कि किसी ने एक परिवर्तनशील के रूप में एक अपरिवर्तनीय संग्रह को पारित किया है जिसने जानबूझकर प्रस्तुत अनुबंध को तोड़ दिया है - यह अनुबंध के साथ ही एक मुद्दा नहीं है, जैसे IList<T>। किसी को बस लागू करने IReadOnlyList<T>और हर विधि एक अपवाद भी फेंक सकता है। यह डक-टाइपिंग के विपरीत है - आपने इसे डक कहा है, लेकिन यह एक जैसा नहीं हो सकता। यह अनुबंध का हिस्सा है, भले ही कंपाइलर इसे लागू न कर सके। मैं 100% सहमत हूँ कि IReadOnlyList<T>या IReadOnlyCollection<T>आसानी से उपयोग के लिए उपयोग किया जाना चाहिए, यद्यपि।
शेल्बी ओल्डफील्ड

93

कुछ लोग कहते हैं "हमेशा के IList<T>बजाय उपयोग करें List<T>"।
वे आपसे अपने विधि हस्ताक्षर बदलना चाहते हैं void Foo(List<T> input)करने के लिए void Foo(IList<T> input)

ये लोग गलत हैं।

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

एक मामूली प्रतिवाद के रूप में, आपको हर एक कॉलर को किसी List<T>भी तरह की आवश्यकता हो सकती है, और कॉलिंग कोड के साथ अटे पड़े हैं.ToList()

लेकिन कहीं अधिक महत्वपूर्ण बात, अगर आप एक पैरामीटर के रूप में एक IList स्वीकार कर रहे हैं तो आप बेहतर सावधान, हो जाएगा, क्योंकि IList<T>और List<T>उसी तरह व्यवहार नहीं करते। नाम में समानता के बावजूद, और एक इंटरफ़ेस साझा करने के बावजूद वे एक ही अनुबंध को उजागर नहीं करते हैं

मान लीजिए कि आपके पास यह तरीका है:

public Foo(List<int> a)
{
    a.Add(someNumber);
}

एक सहायक सहयोगी "रिफैक्टर्स" को स्वीकार करने की विधि है IList<int>

आपका कोड अब टूट गया है, क्योंकि int[]कार्यान्वयन IList<int>, लेकिन निश्चित आकार का है। संग्रह से आइटम जोड़ने या निकालने का प्रयास करने से पहले ध्वज के अनुबंध ICollection<T>(आधार IList<T>) के लिए उस कोड की आवश्यकता होती है जो IsReadOnlyध्वज की जांच करने के लिए इसका उपयोग करता है । के लिए अनुबंध List<T>नहीं करता है।

लिसकोव प्रतिस्थापन सिद्धांत (सरलीकृत) में कहा गया है कि एक प्रकार का आधार आधार प्रकार के स्थान पर उपयोग करने में सक्षम होना चाहिए, जिसमें कोई अतिरिक्त पूर्व शर्त या पोस्टकंडिशन नहीं है।

ऐसा लगता है कि यह Liskov प्रतिस्थापन सिद्धांत को तोड़ता है।

 int[] array = new[] {1, 2, 3};
 IList<int> ilist = array;

 ilist.Add(4); // throws System.NotSupportedException
 ilist.Insert(0, 0); // throws System.NotSupportedException
 ilist.Remove(3); // throws System.NotSupportedException
 ilist.RemoveAt(0); // throws System.NotSupportedException

लेकिन यह नहीं है। इसका उत्तर यह है कि उदाहरण में IList <T> / ICollection <T> का उपयोग गलत है। यदि आप एक ICollection <T> का उपयोग करते हैं, तो आपको IsReadOnly ध्वज की जांच करने की आवश्यकता है।

if (!ilist.IsReadOnly)
{
   ilist.Add(4);
   ilist.Insert(0, 0); 
   ilist.Remove(3);
   ilist.RemoveAt(0);
}
else
{
   // what were you planning to do if you were given a read only list anyway?
}

यदि कोई आपको एक ऐरे या सूची से गुजरता है, तो आपका कोड ठीक काम करेगा यदि आप हर बार ध्वज की जांच करते हैं और कमबैक करते हैं ... लेकिन वास्तव में; ये किसने किया था? क्या आपको पहले से पता नहीं है अगर आपके विधि को एक सूची की आवश्यकता है जो अतिरिक्त सदस्यों को ले सकती है; क्या आप निर्दिष्ट नहीं करते कि विधि हस्ताक्षर में? यदि आप केवल पढ़ने के लिए सूची में पास किए गए तो आप वास्तव में क्या करने जा रहे थे int[]?

आप एक List<T>कोड में विकल्प का उपयोग कर सकते हैं IList<T>/ ICollection<T> सही ढंग से । आप गारंटी नहीं दे सकते कि आप उपयोग करने वाले कोड में IList<T>/ a ICollection<T>को प्रतिस्थापित कर सकते हैं List<T>

ठोस प्रकारों के बजाय अमूर्त का उपयोग करने के लिए बहुत सारे तर्कों में सिंगल रिस्पांसिबिलिटी प्रिंसिपल / इंटरफ़ेस सेग्रिगेशन प्रिंसिपल की अपील है - सबसे कम संभव इंटरफ़ेस पर निर्भर करें। ज्यादातर मामलों में, यदि आप एक का उपयोग कर रहे हैं List<T>और आपको लगता है कि आप इसके बजाय एक संकीर्ण इंटरफ़ेस का उपयोग कर सकते हैं - क्यों नहीं IEnumerable<T>? यदि आप आइटम जोड़ने की आवश्यकता नहीं है तो यह अक्सर बेहतर होता है। यदि आपको संग्रह में जोड़ने की आवश्यकता है, तो ठोस प्रकार का उपयोग करें List<T>,।

मेरे लिए IList<T>(और ICollection<T>) .NET फ्रेमवर्क का सबसे खराब हिस्सा है। IsReadOnlyकम से कम आश्चर्य के सिद्धांत का उल्लंघन करता है। एक वर्ग, जैसे कि Array, जो कभी भी आइटम जोड़ने, डालने या निकालने की अनुमति नहीं देता है, उन्हें ऐड, इंसर्ट और रिमूव मेथड्स के साथ इंटरफ़ेस लागू नहीं करना चाहिए। (यह भी देखें /software/306105/implementing-an-interface-when-you-dont-need-one-of-the-properties )

है IList<T>अपने संगठन के लिए एक अच्छा फिट? यदि कोई सहकर्मी आपको IList<T>इसके बजाय उपयोग करने के लिए एक विधि हस्ताक्षर को बदलने के लिए कहता है List<T>, तो उनसे पूछें कि वे किसी एक तत्व को कैसे जोड़ेंगे IList<T>। यदि वे IsReadOnly(और अधिकांश लोग नहीं जानते हैं) के बारे में नहीं जानते हैं , तो उपयोग न करें IList<T>। कभी।


ध्यान दें कि IsReadOnly ध्वज ICollection <T> से आता है, और इंगित करता है कि क्या आइटम को संग्रह से जोड़ा या हटाया जा सकता है; लेकिन केवल चीजों को वास्तव में भ्रमित करने के लिए, यह इंगित नहीं करता है कि क्या उन्हें प्रतिस्थापित किया जा सकता है, जो एरे के मामले में है (जो कि IsReadOnlys == true पर वापस लौटें) हो सकता है।

IsReadOnly पर अधिक जानकारी के लिए, ICollection की msdn परिभाषा देखें <T> .IsReadOnly


5
बढ़िया, बढ़िया जवाब। मैं इसे जोड़ना चाहूंगा, भले ही IsReadOnlyए के trueलिए हो , फिर भी IListआप इसके वर्तमान सदस्यों को संशोधित कर सकते हैं! शायद उस संपत्ति का नाम होना चाहिए IsFixedSize?
ज़ोफ़'

(जो कि एक के Arrayरूप में उत्तीर्ण होने के साथ परीक्षण किया गया था IList, इसलिए मैं वर्तमान सदस्यों को संशोधित कर सकता हूं)
xofz

1
। यहाँ सूक्ष्म अंतर के बारे में एक विस्तृत मस्तिष्क-पिघलने वाला ब्लॉग है: enterprisecraftsmanship.com/2014/11/22/…
पूर्णतावादी

7
बहुत बढ़िया जवाब! इसके अलावा, .NET 4.6 के बाद से, हमारे पास अब है IReadOnlyCollection<T>और IReadOnlyList<T>जो लगभग हमेशा बेहतर से फिट हैं, IList<T>लेकिन खतरनाक आलसी शब्दार्थ नहीं है IEnumerable<T>। और वे सहसंयोजक हैं। बचो IList<T>!
ZunTzu

37

List<T>का एक विशिष्ट कार्यान्वयन है IList<T>, जो एक कंटेनर है जिसे उसी तरह से संबोधित किया जा सकता है जैसे कि T[]एक पूर्णांक सूचकांक का उपयोग करके एक रैखिक सरणी । जब आप IList<T>विधि के तर्क के प्रकार के रूप में निर्दिष्ट करते हैं , तो आप केवल निर्दिष्ट करते हैं कि आपको कंटेनर की कुछ क्षमताओं की आवश्यकता है।

उदाहरण के लिए, इंटरफ़ेस विनिर्देश एक विशिष्ट डेटा संरचना का उपयोग करने के लिए लागू नहीं करता है। के कार्यान्वयन List<T>, तक पहुँचने को हटाने और एक रेखीय सरणी के रूप में तत्वों को जोड़ने के लिए एक ही प्रदर्शन होता है। हालांकि, आप एक कार्यान्वयन की कल्पना कर सकते हैं जो इसके बजाय एक लिंक्ड सूची द्वारा समर्थित है, जिसके लिए तत्वों को अंत तक जोड़ना सस्ता (निरंतर-समय) लेकिन यादृच्छिक-पहुंच बहुत अधिक महंगा है। (नोट जो .NET LinkedList<T>करता नहीं लागू IList<T>।)

यह उदाहरण आपको यह भी बताता है कि ऐसे हालात हो सकते हैं जब आपको तर्क को सूचीबद्ध करने के लिए कार्यान्वयन की आवश्यकता होती है, इंटरफ़ेस की नहीं, तर्क सूची में: इस उदाहरण में, जब भी आपको किसी विशेष पहुंच प्रदर्शन विशेषता की आवश्यकता होती है। यह आमतौर पर एक कंटेनर के विशिष्ट कार्यान्वयन के लिए गारंटी है ( List<T>प्रलेखन: "यह IList<T>एक सरणी का उपयोग करके जेनेरिक इंटरफ़ेस को लागू करता है जिसका आकार गतिशील रूप से आवश्यकतानुसार बढ़ाया जाता है।")।

इसके अतिरिक्त, आप अपनी ज़रूरत की कम से कम कार्यक्षमता को उजागर करने पर विचार कर सकते हैं। उदाहरण के लिए। यदि आपको सूची की सामग्री को बदलने की आवश्यकता नहीं है, तो आपको संभवतः उपयोग करने पर विचार करना चाहिए IEnumerable<T>, जो IList<T>विस्तारित होता है।


IList के बजाय IEnumerable का उपयोग करने के बारे में अपने अंतिम विवरण के बारे में। यह हमेशा अनुशंसित नहीं होता है, उदाहरण के लिए WPF लें, जो केवल एक आवरण IList ऑब्जेक्ट बनाएगा, जिससे परफ़ेक्ट
HAdes

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

1
@joshperry यदि किसी इंटरफ़ेस का प्रदर्शन आपको परेशान कर रहा है तो आप पहली बार गलत प्लेटफ़ॉर्म में हैं। इम्पो, यह माइक्रोप्टिमाइजेशन है।
नवफाल

@nawfal मैं प्रदर्शन पेशेवरों / इंटरफेस के विपक्ष पर टिप्पणी नहीं कर रहा था। मैं इस तथ्य पर सहमत और टिप्पणी कर रहा था कि जब आप एक ठोस वर्ग को एक तर्क के रूप में उजागर करना चुनते हैं, तो आप एक प्रदर्शन इरादे को संवाद करने में सक्षम होते हैं। ले रहा है LinkedList<T>लेने बनाम List<T>बनाम IList<T>सभी संवाद प्रदर्शन कोड के लिए आवश्यक की गारंटी देता है के बारे में कुछ कहा जा रहा है।
जॉस्पररी

28

मैं इस सवाल को थोड़ा घुमा दूंगा कि आप ठोस कार्यान्वयन पर इंटरफ़ेस का उपयोग क्यों करें, इसके बजाय आप इंटरफ़ेस के बजाय कंक्रीट कार्यान्वयन का उपयोग करने का औचित्य साबित करने का प्रयास करें। यदि आप इसे सही नहीं ठहरा सकते हैं, तो इंटरफ़ेस का उपयोग करें।


1
इसके बारे में सोचने का बहुत दिलचस्प तरीका। और प्रोग्रामिंग करते समय सोचने का एक अच्छा तरीका - धन्यवाद।
मूंगफली

खूब कहा है! चूंकि इंटरफ़ेस अधिक लचीला दृष्टिकोण है, इसलिए आपको वास्तव में यह बताना होगा कि ठोस कार्यान्वयन आपको क्या खरीद रहा है।
कॉरी हाउस

9
सोचने का बढ़िया तरीका। फिर भी मैं इसका उत्तर दे सकता हूं: मेरे कारण को AddRange कहा जाता है ()
PPC

4
मेरे कारण को ऐड () कहा जाता है। कभी-कभी आप एक सूची चाहते हैं जिसे आप जानते हैं कि अतिरिक्त तत्व ले सकते हैं, निश्चित रूप से? मेरा जवाब देखिए।
परफेक्शनिस्ट

19

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

उदाहरण के लिए यदि कोई वर्ग A है और आपका वर्ग B उसे विरासत में मिला है तो आप सूची <T> का उपयोग नहीं कर सकते

class A : B, IList<T> { ... }

15

टीडीडी और ओओपी का एक सिद्धांत आम तौर पर एक कार्यान्वयन नहीं एक इंटरफ़ेस के लिए प्रोग्रामिंग है।

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

ऐसा करने की लागत न्यूनतम है, बाद में खुद को सिरदर्द से क्यों न बचाएं? यह इंटरफ़ेस सिद्धांत क्या है।


3
यदि आपका ExtendedList <T> सूची <T> विरासत में मिला है, तो आप इसे अभी भी सूची <T> अनुबंध में फिट कर सकते हैं। यह तर्क केवल तभी काम करता है जब आप IList <T> का अपना कार्यान्वयन sratch से लिखते हैं (या कम से कम सूची प्राप्त किए बिना <T>)
PPC

14
public void Foo(IList<Bar> list)
{
     // Do Something with the list here.
}

इस मामले में आप किसी भी वर्ग में उत्तीर्ण हो सकते हैं जो IList <Bar> इंटरफ़ेस को लागू करता है। यदि आप इसके बजाय सूची <बार> का उपयोग करते हैं, तो केवल एक सूची <बार> उदाहरण में पारित किया जा सकता है।

IList <Bar> तरीका सूची <Bar> की तुलना में अधिक शिथिल है।


13

यह मानते हुए कि इनमें से कोई भी सूची बनाम IList प्रश्न (या उत्तर) हस्ताक्षर अंतर का उल्लेख नहीं करता है। (यही कारण है कि मैंने एसओ पर इस सवाल की खोज की!)

तो यहाँ उन विधियों को सूचीबद्ध किया गया है जो IList में नहीं पाई जाती हैं, कम से कम .NET 4.5 के रूप में (लगभग 2015)

  • AddRange
  • AsReadOnly
  • द्विआधारी खोज
  • क्षमता
  • सभी को रूपांतरित करें
  • मौजूद
  • खोज
  • सब ढूँढ़ो
  • FindIndex
  • FindLast
  • FindLastIndex
  • प्रत्येक के लिए
  • GetRange
  • InsertRange
  • LastIndexOf
  • सभी हटाएं
  • RemoveRange
  • उलटना
  • तरह
  • toArray
  • TrimExcess
  • TrueForAll

1
पूरी तरह से सच नहीं है। Reverseऔर ToArrayIEnumerable <T> इंटरफ़ेस के लिए विस्तार विधियाँ हैं, जिनसे IList <T> प्राप्त होता है।
तारेक

ऐसा इसलिए है क्योंकि ये केवल Listएस और अन्य कार्यान्वयन में समझदारी रखते हैं IList
HankCa

12

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


7

क्या होगा अगर .NET 5.0 इसकी जगह System.Collections.Generic.List<T>ले ले System.Collection.Generics.LinearList<T>। .NET हमेशा नाम का मालिक है, List<T>लेकिन वे गारंटी देते हैं कि IList<T>एक अनुबंध है। तो IMHO हम (कम से कम I) किसी के नाम का उपयोग करने वाले नहीं हैं (हालाँकि यह इस मामले में .NET है) और बाद में परेशानी में पड़ गए।

उपयोग करने के मामले में IList<T>, फोन करने वाले को हमेशा काम करने के लिए निर्देशित किया जाता है, और कार्यान्वयनकर्ता किसी भी ठोस ठोस कार्यान्वयन के लिए अंतर्निहित संग्रह को बदलने के लिए स्वतंत्र होता हैIList


7

सभी अवधारणाओं को मूल रूप से ऊपर के अधिकांश उत्तर में कहा गया है कि कंक्रीट कार्यान्वयन पर इंटरफ़ेस का उपयोग क्यों करें।

IList<T> defines those methods (not including extension methods)

IList<T> MSDN लिंक

  1. जोड़ना
  2. स्पष्ट
  3. शामिल
  4. को कॉपी
  5. GetEnumerator
  6. के सूचकांक
  7. सम्मिलित करें
  8. हटाना
  9. RemoveAt

List<T> उन नौ तरीकों को लागू करता है (विस्तार विधियों को शामिल नहीं करता है), इसके शीर्ष पर इसके लगभग 41 सार्वजनिक तरीके हैं, जो आपके विचार में वजन करता है कि आपके आवेदन में किसका उपयोग करना है।

List<T> MSDN लिंक


4

क्योंकि आप एक IList या एक ICollection परिभाषित करने के लिए अपने इंटरफेस के अन्य कार्यान्वयन के लिए खुल जाएगा।

आप एक IOrderRepository होना चाहते हैं जो IList या ICollection दोनों में ऑर्डर के संग्रह को परिभाषित करता है। आप तब तक विभिन्न प्रकार के कार्यान्वयन कर सकते हैं जब तक वे आपके IList या ICollection द्वारा परिभाषित "नियमों" के अनुरूप आदेशों की एक सूची प्रदान करते हैं।


3

IList <> अन्य पोस्टर की सलाह के अनुसार लगभग हमेशा बेहतर होता है, हालांकि ध्यान दें कि IList <> WCF DataContitSerializer के साथ क्रमिकरण / विचलन के एक से अधिक चक्र के माध्यम से .NET 3.5 sp 1 में बग है

इस बग को ठीक करने के लिए अब एक SP है: KB 971030


2

इंटरफ़ेस यह सुनिश्चित करता है कि आप कम से कम उन तरीकों को प्राप्त करें जिनकी आप अपेक्षा कर रहे हैं ; इंटरफ़ेस की परिभाषा के बारे में पता होना। सभी अमूर्त विधियाँ जो कि इंटरफ़ेस को विरासत में देने वाले किसी भी वर्ग द्वारा लागू की जानी हैं। इसलिए यदि कोई व्यक्ति कुछ तरीकों के अलावा इंटरफ़ेस से विरासत में मिला है, उसके अलावा कई तरीकों से अपना खुद का एक विशाल वर्ग बनाता है, और जो आपके लिए किसी काम के नहीं हैं, तो उप-संदर्भ के संदर्भ में इसका उपयोग करना बेहतर होगा (इस मामले में) इंटरफ़ेस) और इसे ठोस वर्ग ऑब्जेक्ट असाइन करें।

अतिरिक्त लाभ यह है कि आपका कोड ठोस वर्ग में किसी भी परिवर्तन से सुरक्षित है क्योंकि आप केवल ठोस वर्ग के कुछ तरीकों की सदस्यता ले रहे हैं और वे वही हैं जो तब तक होने जा रहे हैं जब तक कि कंक्रीट वर्ग आपको इंटरफ़ेस से विरासत में मिला है। का उपयोग करते हुए। इसलिए आपकी सुरक्षा और कोडर के लिए स्वतंत्रता जो अपने ठोस वर्ग में अधिक कार्यक्षमता को बदलने या जोड़ने के लिए ठोस कार्यान्वयन लिख रहा है।


2

आप इस तर्क को एक शुद्ध OO दृष्टिकोण सहित कई कोणों से देख सकते हैं, जो एक इंटरफ़ेस के खिलाफ कार्यक्रम को लागू करने के लिए नहीं कहता है। इस विचार के साथ, IList का उपयोग उसी प्रिंसिपल का अनुसरण करता है जो चारों ओर से गुजरता है और इंटरफेसेस का उपयोग करता है जिसे आप स्क्रैच से परिभाषित करते हैं। मैं एक इंटरफ़ेस द्वारा सामान्य रूप से प्रदान की जाने वाली मापनीयता और लचीलेपन कारकों में भी विश्वास करता हूं। यदि IList <T> को निहित करने वाले वर्ग को विस्तारित या परिवर्तित करने की आवश्यकता है, तो उपभोग कोड को बदलना नहीं है; यह जानता है कि IList इंटरफ़ेस अनुबंध किसका पालन करता है। हालाँकि, एक ठोस कार्यान्वयन और सूची <T> का उपयोग करके एक वर्ग जो बदलता है, कॉलिंग कोड को भी बदलने की आवश्यकता हो सकती है। इसका कारण यह है कि IList <T> का पालन करने वाला एक वर्ग एक निश्चित व्यवहार की गारंटी देता है जो सूची <T> का उपयोग करके एक ठोस प्रकार की गारंटी नहीं है।

ऐसा करने की शक्ति भी है कि सूची के डिफ़ॉल्ट कार्यान्वयन को लागू करने की तरह <t> एक वर्ग पर लागू करने के लिए IList <T> के लिए। कहते हैं। संशोधन, .Rove या किसी अन्य IList विधि डेवलपर को बहुत लचीलापन और शक्ति प्रदान करता है, अन्यथा संशोधित नहीं। सूची <टी> द्वारा


0

आमतौर पर, एक अच्छा तरीका यह है कि आप अपने सार्वजनिक सामना करने वाले एपीआई में IList का उपयोग करें (जब उचित हो, और सूची शब्दार्थ आवश्यक हो), और फिर एपीआई को लागू करने के लिए आंतरिक रूप से सूचीबद्ध करें। यह आपको अपनी कक्षा का उपयोग करने वाले कोड को तोड़ने के बिना IList के एक अलग कार्यान्वयन में बदलने की अनुमति देता है।

वर्ग नाम सूची को अगली .net फ्रेमवर्क में बदला जा सकता है लेकिन इंटरफ़ेस अनुबंध के रूप में कभी भी बदलने वाला नहीं है।

ध्यान दें, यदि आपका API केवल foreach loops इत्यादि में उपयोग होने वाला है, तो आप इसके बजाय IEnumerable को उजागर करने पर विचार करना चाह सकते हैं।

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