क्या कोई मुझे समझा सकता है कि मैं C # पर IList over List का उपयोग क्यों करना चाहूंगा?
संबंधित प्रश्न: क्यों उजागर करना बुरा माना जाता हैList<T>
क्या कोई मुझे समझा सकता है कि मैं C # पर IList over List का उपयोग क्यों करना चाहूंगा?
संबंधित प्रश्न: क्यों उजागर करना बुरा माना जाता हैList<T>
जवाबों:
यदि आप अपनी कक्षा को एक पुस्तकालय के माध्यम से उजागर कर रहे हैं जिसका उपयोग अन्य लोग करेंगे, तो आप आम तौर पर इसे ठोस कार्यान्वयन के बजाय इंटरफेस के माध्यम से उजागर करना चाहते हैं। यदि आप बाद में एक अलग ठोस वर्ग का उपयोग करने के लिए अपनी कक्षा के कार्यान्वयन को बदलने का निर्णय लेते हैं तो यह मदद करेगा। उस स्थिति में जब तक इंटरफ़ेस नहीं बदलेगा, आपके पुस्तकालय के उपयोगकर्ताओं को अपना कोड अपडेट करने की आवश्यकता नहीं होगी।
यदि आप इसे आंतरिक रूप से उपयोग कर रहे हैं, तो आप इतना ध्यान नहीं दे सकते हैं, और उपयोग List<T>
करना ठीक हो सकता है।
कम लोकप्रिय जवाब प्रोग्रामर है जैसे अपने सॉफ्टवेयर का ढोंग करना दुनिया भर में फिर से इस्तेमाल किया जा रहा है, जब परियोजनाओं के बहुमत को बनाए रखना बहुत कम लोगों द्वारा बनाए रखा जाएगा और हालांकि अच्छा इंटरफ़ेस-संबंधित साउंडबाइट हैं, तो आप बहक रहे हैं स्वयं।
वास्तुकला अंतरिक्ष यात्री । संभावना है कि आप कभी भी अपना खुद का आईएलस्ट लिखेंगे जो .NET फ्रेमवर्क में पहले से ही कुछ भी जोड़ता है, वे इतने दूरस्थ हैं कि यह "सर्वश्रेष्ठ प्रथाओं" के लिए सैद्धांतिक जेली टॉट्स आरक्षित है।
जाहिर है अगर आपसे पूछा जा रहा है कि आप एक साक्षात्कार में किसका उपयोग करते हैं, तो आप कहते हैं कि आइलिस्ट, मुस्कुराओ, और दोनों अपने आप को बहुत चालाक होने के लिए प्रसन्न दिखते हैं। या एपीआई, IList का सामना करने वाली जनता के लिए। उम्मीद है कि आपको मेरी बात सही लगेगी।
IEnumerable<string>
अंदर है, मैं List<string>
अपने संग्रह को उत्पन्न करने के लिए आंतरिक बैकिंग स्टोर के लिए उपयोग कर सकता हूं, लेकिन मैं केवल कॉलर्स को यह बताना चाहता हूं कि यह सामग्री है, न कि जोड़ना या निकालना। एक पैरामीटर के रूप में एक इंटरफ़ेस को स्वीकार करना एक समान संदेश का संचार करता है "मुझे स्ट्रिंग्स के संग्रह की आवश्यकता है, हालांकि चिंता न करें, मैं इसे नहीं बदलूंगा।"
इंटरफ़ेस एक वादा (या एक अनुबंध) है।
जैसा कि यह हमेशा वादों के साथ होता है - बेहतर से छोटा ।
IList
वादा है। यहां कौन सा छोटा और बेहतर वादा है? यह तर्कसंगत नहीं है।
List<T>
, क्योंकि AddRange
इंटरफ़ेस पर परिभाषित नहीं किया गया है।
IList<T>
वादा करता है कि यह नहीं रख सकता है। उदाहरण के लिए, वहाँ एक Add
विधि से फेंक सकता है अगर IList<T>
केवल पढ़ने के लिए होता है। List<T>
दूसरी ओर हमेशा लिखने योग्य होता है और इस प्रकार हमेशा अपने वादे करता रहता है। इसके अलावा, .NET 4.6 के बाद से, अब हमारे पास है IReadOnlyCollection<T>
और IReadOnlyList<T>
जो लगभग हमेशा से बेहतर हैं IList<T>
। और वे सहसंयोजक हैं। बचो IList<T>
!
IList<T>
। किसी को बस लागू करने IReadOnlyList<T>
और हर विधि एक अपवाद भी फेंक सकता है। यह डक-टाइपिंग के विपरीत है - आपने इसे डक कहा है, लेकिन यह एक जैसा नहीं हो सकता। यह अनुबंध का हिस्सा है, भले ही कंपाइलर इसे लागू न कर सके। मैं 100% सहमत हूँ कि IReadOnlyList<T>
या IReadOnlyCollection<T>
आसानी से उपयोग के लिए उपयोग किया जाना चाहिए, यद्यपि।
कुछ लोग कहते हैं "हमेशा के 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
IsReadOnly
ए के true
लिए हो , फिर भी IList
आप इसके वर्तमान सदस्यों को संशोधित कर सकते हैं! शायद उस संपत्ति का नाम होना चाहिए IsFixedSize
?
Array
रूप में उत्तीर्ण होने के साथ परीक्षण किया गया था IList
, इसलिए मैं वर्तमान सदस्यों को संशोधित कर सकता हूं)
IReadOnlyCollection<T>
और IReadOnlyList<T>
जो लगभग हमेशा बेहतर से फिट हैं, IList<T>
लेकिन खतरनाक आलसी शब्दार्थ नहीं है IEnumerable<T>
। और वे सहसंयोजक हैं। बचो IList<T>
!
List<T>
का एक विशिष्ट कार्यान्वयन है IList<T>
, जो एक कंटेनर है जिसे उसी तरह से संबोधित किया जा सकता है जैसे कि T[]
एक पूर्णांक सूचकांक का उपयोग करके एक रैखिक सरणी । जब आप IList<T>
विधि के तर्क के प्रकार के रूप में निर्दिष्ट करते हैं , तो आप केवल निर्दिष्ट करते हैं कि आपको कंटेनर की कुछ क्षमताओं की आवश्यकता है।
उदाहरण के लिए, इंटरफ़ेस विनिर्देश एक विशिष्ट डेटा संरचना का उपयोग करने के लिए लागू नहीं करता है। के कार्यान्वयन List<T>
, तक पहुँचने को हटाने और एक रेखीय सरणी के रूप में तत्वों को जोड़ने के लिए एक ही प्रदर्शन होता है। हालांकि, आप एक कार्यान्वयन की कल्पना कर सकते हैं जो इसके बजाय एक लिंक्ड सूची द्वारा समर्थित है, जिसके लिए तत्वों को अंत तक जोड़ना सस्ता (निरंतर-समय) लेकिन यादृच्छिक-पहुंच बहुत अधिक महंगा है। (नोट जो .NET LinkedList<T>
करता नहीं लागू IList<T>
।)
यह उदाहरण आपको यह भी बताता है कि ऐसे हालात हो सकते हैं जब आपको तर्क को सूचीबद्ध करने के लिए कार्यान्वयन की आवश्यकता होती है, इंटरफ़ेस की नहीं, तर्क सूची में: इस उदाहरण में, जब भी आपको किसी विशेष पहुंच प्रदर्शन विशेषता की आवश्यकता होती है। यह आमतौर पर एक कंटेनर के विशिष्ट कार्यान्वयन के लिए गारंटी है ( List<T>
प्रलेखन: "यह IList<T>
एक सरणी का उपयोग करके जेनेरिक इंटरफ़ेस को लागू करता है जिसका आकार गतिशील रूप से आवश्यकतानुसार बढ़ाया जाता है।")।
इसके अतिरिक्त, आप अपनी ज़रूरत की कम से कम कार्यक्षमता को उजागर करने पर विचार कर सकते हैं। उदाहरण के लिए। यदि आपको सूची की सामग्री को बदलने की आवश्यकता नहीं है, तो आपको संभवतः उपयोग करने पर विचार करना चाहिए IEnumerable<T>
, जो IList<T>
विस्तारित होता है।
LinkedList<T>
लेने बनाम List<T>
बनाम IList<T>
सभी संवाद प्रदर्शन कोड के लिए आवश्यक की गारंटी देता है के बारे में कुछ कहा जा रहा है।
मैं इस सवाल को थोड़ा घुमा दूंगा कि आप ठोस कार्यान्वयन पर इंटरफ़ेस का उपयोग क्यों करें, इसके बजाय आप इंटरफ़ेस के बजाय कंक्रीट कार्यान्वयन का उपयोग करने का औचित्य साबित करने का प्रयास करें। यदि आप इसे सही नहीं ठहरा सकते हैं, तो इंटरफ़ेस का उपयोग करें।
IList <T> एक ऐसा इंटरफ़ेस है जिससे आप किसी अन्य वर्ग को विरासत में प्राप्त कर सकते हैं और फिर भी सूची <T> को विरासत में लेते हुए IList <T> को लागू कर सकते हैं।
उदाहरण के लिए यदि कोई वर्ग A है और आपका वर्ग B उसे विरासत में मिला है तो आप सूची <T> का उपयोग नहीं कर सकते
class A : B, IList<T> { ... }
टीडीडी और ओओपी का एक सिद्धांत आम तौर पर एक कार्यान्वयन नहीं एक इंटरफ़ेस के लिए प्रोग्रामिंग है।
इस विशिष्ट मामले में जब से आप अनिवार्य रूप से एक भाषा के निर्माण के बारे में बात कर रहे हैं, एक कस्टम नहीं यह आम तौर पर कोई फर्क नहीं पड़ेगा, लेकिन उदाहरण के लिए कहें कि आपने पाया लिस्ट ने आपकी ज़रूरत का समर्थन नहीं किया। यदि आपने बाकी ऐप में IList का उपयोग किया था, तो आप अपने स्वयं के कस्टम वर्ग के साथ सूची का विस्तार कर सकते हैं और फिर भी बिना रीफ़ॉर्मिंग के उस पास को पास करने में सक्षम हो सकते हैं।
ऐसा करने की लागत न्यूनतम है, बाद में खुद को सिरदर्द से क्यों न बचाएं? यह इंटरफ़ेस सिद्धांत क्या है।
public void Foo(IList<Bar> list)
{
// Do Something with the list here.
}
इस मामले में आप किसी भी वर्ग में उत्तीर्ण हो सकते हैं जो IList <Bar> इंटरफ़ेस को लागू करता है। यदि आप इसके बजाय सूची <बार> का उपयोग करते हैं, तो केवल एक सूची <बार> उदाहरण में पारित किया जा सकता है।
IList <Bar> तरीका सूची <Bar> की तुलना में अधिक शिथिल है।
यह मानते हुए कि इनमें से कोई भी सूची बनाम IList प्रश्न (या उत्तर) हस्ताक्षर अंतर का उल्लेख नहीं करता है। (यही कारण है कि मैंने एसओ पर इस सवाल की खोज की!)
तो यहाँ उन विधियों को सूचीबद्ध किया गया है जो IList में नहीं पाई जाती हैं, कम से कम .NET 4.5 के रूप में (लगभग 2015)
Reverse
और ToArray
IEnumerable <T> इंटरफ़ेस के लिए विस्तार विधियाँ हैं, जिनसे IList <T> प्राप्त होता है।
List
एस और अन्य कार्यान्वयन में समझदारी रखते हैं IList
।
कार्यान्वयन पर इंटरफेस का उपयोग करने के लिए सबसे महत्वपूर्ण मामला आपके एपीआई के मापदंडों में है। यदि आपका एपीआई एक सूची पैरामीटर लेता है, तो जो भी इसका उपयोग करता है उसे सूची का उपयोग करना होगा। यदि पैरामीटर प्रकार IList है, तो कॉलर को बहुत अधिक स्वतंत्रता है, और उन कक्षाओं का उपयोग कर सकते हैं जिनके बारे में आपने कभी नहीं सुना है, जो आपके कोड लिखे जाने पर भी अस्तित्व में नहीं हो सकते हैं।
क्या होगा अगर .NET 5.0 इसकी जगह System.Collections.Generic.List<T>
ले ले System.Collection.Generics.LinearList<T>
। .NET हमेशा नाम का मालिक है, List<T>
लेकिन वे गारंटी देते हैं कि IList<T>
एक अनुबंध है। तो IMHO हम (कम से कम I) किसी के नाम का उपयोग करने वाले नहीं हैं (हालाँकि यह इस मामले में .NET है) और बाद में परेशानी में पड़ गए।
उपयोग करने के मामले में IList<T>
, फोन करने वाले को हमेशा काम करने के लिए निर्देशित किया जाता है, और कार्यान्वयनकर्ता किसी भी ठोस ठोस कार्यान्वयन के लिए अंतर्निहित संग्रह को बदलने के लिए स्वतंत्र होता हैIList
सभी अवधारणाओं को मूल रूप से ऊपर के अधिकांश उत्तर में कहा गया है कि कंक्रीट कार्यान्वयन पर इंटरफ़ेस का उपयोग क्यों करें।
IList<T> defines those methods (not including extension methods)
IList<T>
MSDN लिंक
List<T>
उन नौ तरीकों को लागू करता है (विस्तार विधियों को शामिल नहीं करता है), इसके शीर्ष पर इसके लगभग 41 सार्वजनिक तरीके हैं, जो आपके विचार में वजन करता है कि आपके आवेदन में किसका उपयोग करना है।
List<T>
MSDN लिंक
क्योंकि आप एक IList या एक ICollection परिभाषित करने के लिए अपने इंटरफेस के अन्य कार्यान्वयन के लिए खुल जाएगा।
आप एक IOrderRepository होना चाहते हैं जो IList या ICollection दोनों में ऑर्डर के संग्रह को परिभाषित करता है। आप तब तक विभिन्न प्रकार के कार्यान्वयन कर सकते हैं जब तक वे आपके IList या ICollection द्वारा परिभाषित "नियमों" के अनुरूप आदेशों की एक सूची प्रदान करते हैं।
IList <> अन्य पोस्टर की सलाह के अनुसार लगभग हमेशा बेहतर होता है, हालांकि ध्यान दें कि IList <> WCF DataContitSerializer के साथ क्रमिकरण / विचलन के एक से अधिक चक्र के माध्यम से .NET 3.5 sp 1 में बग है ।
इस बग को ठीक करने के लिए अब एक SP है: KB 971030
इंटरफ़ेस यह सुनिश्चित करता है कि आप कम से कम उन तरीकों को प्राप्त करें जिनकी आप अपेक्षा कर रहे हैं ; इंटरफ़ेस की परिभाषा के बारे में पता होना। सभी अमूर्त विधियाँ जो कि इंटरफ़ेस को विरासत में देने वाले किसी भी वर्ग द्वारा लागू की जानी हैं। इसलिए यदि कोई व्यक्ति कुछ तरीकों के अलावा इंटरफ़ेस से विरासत में मिला है, उसके अलावा कई तरीकों से अपना खुद का एक विशाल वर्ग बनाता है, और जो आपके लिए किसी काम के नहीं हैं, तो उप-संदर्भ के संदर्भ में इसका उपयोग करना बेहतर होगा (इस मामले में) इंटरफ़ेस) और इसे ठोस वर्ग ऑब्जेक्ट असाइन करें।
अतिरिक्त लाभ यह है कि आपका कोड ठोस वर्ग में किसी भी परिवर्तन से सुरक्षित है क्योंकि आप केवल ठोस वर्ग के कुछ तरीकों की सदस्यता ले रहे हैं और वे वही हैं जो तब तक होने जा रहे हैं जब तक कि कंक्रीट वर्ग आपको इंटरफ़ेस से विरासत में मिला है। का उपयोग करते हुए। इसलिए आपकी सुरक्षा और कोडर के लिए स्वतंत्रता जो अपने ठोस वर्ग में अधिक कार्यक्षमता को बदलने या जोड़ने के लिए ठोस कार्यान्वयन लिख रहा है।
आप इस तर्क को एक शुद्ध OO दृष्टिकोण सहित कई कोणों से देख सकते हैं, जो एक इंटरफ़ेस के खिलाफ कार्यक्रम को लागू करने के लिए नहीं कहता है। इस विचार के साथ, IList का उपयोग उसी प्रिंसिपल का अनुसरण करता है जो चारों ओर से गुजरता है और इंटरफेसेस का उपयोग करता है जिसे आप स्क्रैच से परिभाषित करते हैं। मैं एक इंटरफ़ेस द्वारा सामान्य रूप से प्रदान की जाने वाली मापनीयता और लचीलेपन कारकों में भी विश्वास करता हूं। यदि IList <T> को निहित करने वाले वर्ग को विस्तारित या परिवर्तित करने की आवश्यकता है, तो उपभोग कोड को बदलना नहीं है; यह जानता है कि IList इंटरफ़ेस अनुबंध किसका पालन करता है। हालाँकि, एक ठोस कार्यान्वयन और सूची <T> का उपयोग करके एक वर्ग जो बदलता है, कॉलिंग कोड को भी बदलने की आवश्यकता हो सकती है। इसका कारण यह है कि IList <T> का पालन करने वाला एक वर्ग एक निश्चित व्यवहार की गारंटी देता है जो सूची <T> का उपयोग करके एक ठोस प्रकार की गारंटी नहीं है।
ऐसा करने की शक्ति भी है कि सूची के डिफ़ॉल्ट कार्यान्वयन को लागू करने की तरह <t> एक वर्ग पर लागू करने के लिए IList <T> के लिए। कहते हैं। संशोधन, .Rove या किसी अन्य IList विधि डेवलपर को बहुत लचीलापन और शक्ति प्रदान करता है, अन्यथा संशोधित नहीं। सूची <टी> द्वारा
आमतौर पर, एक अच्छा तरीका यह है कि आप अपने सार्वजनिक सामना करने वाले एपीआई में IList का उपयोग करें (जब उचित हो, और सूची शब्दार्थ आवश्यक हो), और फिर एपीआई को लागू करने के लिए आंतरिक रूप से सूचीबद्ध करें। यह आपको अपनी कक्षा का उपयोग करने वाले कोड को तोड़ने के बिना IList के एक अलग कार्यान्वयन में बदलने की अनुमति देता है।
वर्ग नाम सूची को अगली .net फ्रेमवर्क में बदला जा सकता है लेकिन इंटरफ़ेस अनुबंध के रूप में कभी भी बदलने वाला नहीं है।
ध्यान दें, यदि आपका API केवल foreach loops इत्यादि में उपयोग होने वाला है, तो आप इसके बजाय IEnumerable को उजागर करने पर विचार करना चाह सकते हैं।