2012-04-16 6 views
5

संभव डुप्लिकेट:
Collection<T> versus List<T> what should you use on your interfaces?एक IEnumerable <T> या ICollection <T> रूप में एक आंतरिक सूची <T> लौटने के लिए ठीक?

इस विधि-लौटे चर myVar पर विचार करें एक List<T> है, लेकिन विधि MyMethod() की वापसी प्रकार एक IEnumerable<T> है:

public IEnumerable<T> MyMethod(string stuff) 
{ 
    var myVar = new List<T>(); 
    //do stuff 

    return myVar; 
} 

अनिवार्य रूप से, मैं क्या जानना चाहता हूं अगर रिटर्न है एनजी myVar एक अलग प्रकार के रूप में ठीक है।

विशेष रूप से, मेरी स्थिति के संबंध में, 'डू स्टफ' DataRow के माध्यम से जाता है और वस्तुओं की सूची में DataRow में आइटम असाइन करता है। मेरे पास ICollection और IList अन्य स्थानों पर रिटर्न प्रकारों के साथ समान स्थितियां भी हैं।

कारण मैं वापस जाने के लिए या तो IEnumerable या ICollection है ताकि मैं जरूरत से ज्यादा वापस नहीं कर रहा हूँ चाहता हूँ। लेकिन साथ ही, यह कॉलर को लौटाए गए मान को List पर बदलने की अनुमति देता है यदि उसे ऐसा करने की आवश्यकता है।

हालांकि, यह अजीब लगता है कि मेरा रिटर्न स्टेटमेंट List लौटा रहा है, विधि के रिटर्न प्रकार के बजाय। क्या यह सामान्य अभ्यास है? क्या ऐसा करने में कुछ गड़बड़ है?

स्पष्टीकरण (शिकार टिप्पणियों के जवाब में):

बस स्पष्ट करने के लिए, क्या मैं उत्सुक हूँ है के बारे में है, तो यह ठीक है कि शरीर में मेरी वापसी कथन एक List<T> लौटा रहा है है, लेकिन विधि हैडर IEnumerable, या संभवतः ICollection, Collection, आदि की वापसी प्रकार ... कुछ अलग पिण्डों से से लौटने के बयान है।

+2

कॉलर कभी भी आईनेमेरेबल से सूची में परिवर्तित नहीं होना चाहिए। एक इंटरफ़ेस लौटने का कारण यह है कि इससे कोई फर्क नहीं पड़ता कि अंतर्निहित सूची, ऑबरवेबल संग्रह, सरल सरणी या यहां तक ​​कि उपज रिटर्न के माध्यम से एक सूची है। – aqwert

+1

दो सुझाए गए डुप्लस इस प्रश्न के मुकाबले एक-दूसरे के डुप्लिकेट के करीब हैं, मुझे लगता है, हालांकि वे सभी निकट से संबंधित हैं। –

+0

@ क्रिसशहरबारुक मैं मानता हूं कि यह प्रश्न एक डुप्लिकेट नहीं है और मैंने आशा व्यक्त की है कि मैं यह मानता हूं कि मुझे क्या लगता है कि यह अद्वितीय है। मैंने सवाल फिर से खोलने के लिए भी वोट दिया है। – DavidRR

उत्तर

6

न केवल इसके साथ कुछ भी गलत है, लेकिन यह वास्तव में अच्छा अभ्यास है: केवल सख्ती से जरूरी है। इस तरह, कॉलर इस तथ्य पर भरोसा नहीं कर सकता कि विधि List<T> लौटाएगी, इसलिए अगर किसी कारण से आपको कुछ और लौटने के लिए कार्यान्वयन को बदलने की जरूरत है, तो आप अपना अनुबंध तोड़ नहीं देंगे। हालांकि कॉलिंग कोड तोड़ सकता है अगर यह (गलती से) विधि वास्तव में क्या विधि देता है, इस बारे में धारणाएं बनाते हैं।

+0

".... और कॉलर इसे किसी सूची में परिवर्तित कर सकता है अगर उसे" लगता है कि यह पहले से ही इरादा है, अभी भी अच्छा अभ्यास है? –

+0

@TimSchmelter, ठीक है, अगर कॉलर को * यह माना जाता है कि विधि एक सूची लौटाती है, तो वापसी का प्रकार सूची होना चाहिए, बेशक ... यह अच्छी प्रथा का भी मामला नहीं है, केवल सामान्य ज्ञान का मामला ;) –

+0

तो फिर सत्यापित करने के लिए, मेरा रिटर्न स्टेटमेंट एक सूची देता है, लेकिन विधि का रिटर्न प्रकार IENumerable है, यह ठीक है? – RJP

2

इसमें कुछ भी गलत नहीं है।

असल में लौटने ठोस वर्ग को पूरा करने के लिए एक ही रास्ता है आवश्यकता "इंटरफेस रिटर्न"।

कमियां हो यदि आप विशेष रूप से कक्षाओं का ज्ञान कोड (List<T> r = (List<T>)MyMethod("ff")) कॉल करने में चुपके से दे सकता है। लेकिन यदि आप परिणाम को इंटरफ़ेस के रूप में देखते हैं (जैसा कि आपको माना जाता है) यह ठीक है।

3

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

दूसरे, IEnumerable<T> से List<T> इनहेरिट करती है।

संपादित करें: थॉमस के रूप में एक टिप्पणी है कि IEnumerable<T> एक List<T> वापस करने के लिए डाली जा सकता है और संशोधित कॉल करने वाले को में विस्तार से बताया। यदि आपका मुख्य लक्ष्य इसे केवल पढ़ने के लिए है, तो आप सूची को myVar.AsReadOnly() के रूप में वापस कर सकते हैं।लेकिन फिर ReadOnlyCollection<T> है।

+0

यह सुनिश्चित नहीं है कि संशोधन की रोकथाम मुख्य कारण – zerkms

+1

यह कॉलर को सूची संशोधित करने से नहीं रोकेगा: कॉलिंग कोड अभी भी परिणाम पर परिणाम डाला जा सकता है। हालांकि, ऐसा करने का अर्थ कार्यान्वयन के बारे में अनियंत्रित धारणा बनाना है, इसलिए कार्यान्वयन में परिवर्तन होने पर यह तोड़ सकता है। –

+0

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

1

मुझे लगता है कि यह इष्टतम नहीं है, क्योंकि यह कॉलर को List<T> पर डालने की अनुमति देता है, जो कार्यान्वयन विस्तार पर निर्भर करता है। मैं Select(x=>x) जैसे किसी प्रकार का मास्किंग जोड़ूंगा।

गतिशील रूप से टाइप किए गए कॉलर को यह भी ध्यान नहीं दिया जा सकता है कि आपने अपनी सूची IEnumerable<T> पर डाली है। उसके लिए यह बस List<T> है।

IEnumerable<T> के रूप में एक आंतरिक स्थायी List<T> लौटाना बहुत गलत होगा, क्योंकि यह कॉलर को आपकी कक्षा की आंतरिक स्थिति को बदलने की अनुमति देता है। लेकिन चूंकि आप प्रत्येक कॉल पर List<T> का एक नया उदाहरण लौटाते हैं, जिसका उपयोग कहीं और नहीं किया जाता है, यह तर्क आपके उदाहरण में लागू नहीं होता है।

+0

यदि आप इस तरह से जाना चाहते हैं, तो आप एक इटरेटर का भी उपयोग कर सकते हैं;) –

+0

किसी चीज़ में सूची को लपेटना बेकार रनटाइम सामान जोड़ता है। लेकिन शायद कोई 'सूची ' 100 में से 99 बार वापस लौटा सकता है, और कभी-कभी केवल एक रैपर लौटा सकता है? वह कोड को तोड़ देगा जो 'सूची' पर रहता है, लेकिन प्रदर्शन को बहुत बुरी तरह चोट नहीं पहुंचाता है। – supercat

+0

@supercat चूंकि 99% कोड के लिए यह छोटा ओवरहेड कोई फर्क नहीं पड़ता, मैं केवल इसके बारे में चिंता करता हूं अगर मेरी प्रोफाइलिंग ने संकेत दिया कि यह महत्वपूर्ण है। – CodesInChaos

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