2009-03-02 12 views
15

फ़ंक्शन से उसी प्रकार की एकाधिक ऑब्जेक्ट्स लौटने पर पसंदीदा कंटेनर प्रकार क्या होता है?क्या मुझे किसी फ़ंक्शन से सरणी या संग्रह वापस करना चाहिए?

क्या यह एक साधारण सरणी (जैसे माईटाइप []) को वापस करने के लिए अच्छा अभ्यास है, या आपको इसे सामान्य जेनेरिक कंटेनर में लपेटना चाहिए (जैसे आईसीओलेक्शन < मायटाइप >)?

धन्यवाद!

+0

(हाल ही में दो प्रतियों से मर्ज किए गए जवाब) –

उत्तर

15

एरिक लिपर्ट के पास article अच्छा है। यदि आपको पूरे लेख को पढ़ने के लिए परेशान नहीं किया जा सकता है, तो जवाब है: इंटरफ़ेस वापस करें।

+0

+1 के उपयोग के बारे में सुनिश्चित नहीं हो सकते हैं, अगर आपने पहले ही ऐसा नहीं किया होता तो उसी लिंक को पोस्ट किया होता। –

+0

ग्रेट मिल! मैं इसे अभी पढ़ रहा हूँ। धन्यवाद! – Pwninstein

0

जेनिक्स का उपयोग करें। अन्य संग्रह वर्गों के साथ अंतःक्रिया करना आसान है और टाइप सिस्टम संभावित त्रुटियों के साथ आपकी सहायता करने में सक्षम है।

एक सरणी लौटने की पुरानी शैली जेनरिक से पहले एक बैसाखी था।

3

हमेशा एक इंटरफ़ेस प्रकार लौटाएं जो कॉलर को सबसे बड़ी कार्यक्षमता प्रस्तुत करता है। तो आपके मामले में ICollection<YourType> का उपयोग किया जाना चाहिए।

कुछ दिलचस्प बात यह है कि बीसीएल डेवलपर्स को वास्तव में .NET ढांचे के कुछ स्थान पर यह गलत मिला - उस कहानी के लिए this Eric Lippert blog post देखें।

+0

वे कहते हैं, वे गलत नहीं मिला है, लेकिन वे एक विकल्प के रूप में उपलब्ध जेनरिक नहीं था (वे थे सीएलआर 2.0 में पेश किया गया)। – erikkallen

+0

मुझे पता है कि आप क्या प्राप्त कर रहे हैं लेकिन लेख उद्धृत करने के लिए: "मैं आपको एक उदाहरण देता हूं कि हमें ढांचे में एक बहुत ही दृश्यमान तरीके से उस भयंकर रूप से गलत कहां मिला।" :) –

6

List<T> क्यों नहीं?

एरिक Lippert पोस्ट दूसरों के द्वारा उल्लेख से, मैंने सोचा कि मैं इस पर प्रकाश डाला जाएगा:

मैं एक दृश्य की जरूरत है मैं IEnumerable<T> इस्तेमाल करेंगे, अगर मैं डेटा मैं करने के लिए सन्निहित नंबरों से एक मानचित्रण की जरूरत 'करेंगे एक List<T> उपयोग करते हैं, अगर मैं मनमाने ढंग से डेटा के पार एक मानचित्रण जरूरत है मैं एक Dictionary<K,V> इस्तेमाल करेंगे, मैं एक HashSet<T> इस्तेमाल करेंगे अगर मैं एक सेट की जरूरत है। मुझे बस कुछ भी के लिए सरणी की आवश्यकता नहीं है, इसलिए मैं लगभग उनका उपयोग नहीं करता हूं। वे किसी समस्या को हल नहीं करते हैं I मेरे निपटान के अन्य उपकरणों की तुलना में बेहतर है।

+0

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

0

क्या कभी अपने कोड, अधिक पठनीय पोषणीय और आप के लिए आसान बनाता है। मैं सामान्य सरणी का उपयोग करता था, सरल == अधिकतर समय में बेहतर होता। हालांकि मुझे सही जवाब देने के लिए वास्तव में संदर्भ देखना है।

4
return ICollection<type> 

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

1

IList<MyType> क्यों नहीं?

यह प्रत्यक्ष अनुक्रमण का समर्थन करता है जो किसी दिन के लिए List<MyType> वापस करने की संभावना को हटाए बिना सरणी के लिए हॉलमार्क है। यदि आप इस सुविधा को दबाना चाहते हैं, तो आप शायद IEnumerable<MyType> वापस करना चाहते हैं।

5

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

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

उदाहरण के लिए, यदि आप किसी विशेष फ़ाइल के लिए खोज के परिणाम वापस करना चाहते हैं, तो IEnumerable<FileInfo> लौटाएं।

हालांकि, यदि आप किसी निर्देशिका में फ़ाइलों का पर्दाफाश करना चाहते हैं, तो आप IList/ICollection<FileInfo> का पर्दाफाश करेंगे क्योंकि यह समझ में आता है कि आप संभवतः संग्रह की सामग्री को बदलना चाहते हैं।

+0

IEnumerabl _not_ केवल पढ़ने-योग्य संग्रह है। यह अनुक्रम और गीलेर के लिए एक सामान्य इंटरफ़ेस है, तत्व अपरिवर्तनीय हैं या टी की वस्तुओं पर निर्भर नहीं हैं या नहीं। सूची का कोई ऑब्जेक्ट एक आईनेमरेबल है लेकिन यह निश्चित रूप से सूची एक पठन-संग्रह संग्रह नहीं बनाता है –

+0

@runefs: आप गलत पढ़ते हैं। मैं वापस आने वाले उदाहरणों की अपरिवर्तनीयता के बारे में बात नहीं कर रहा हूं, बल्कि, अनुक्रम की अपरिवर्तनीयता। – casperOne

0

किसी अन्य चीज़ पर आईन्यूमेरेबल के पक्ष में बड़े फायदे हैं, क्योंकि इससे आपको सबसे बड़ी कार्यान्वयन लचीलापन मिलती है और आपको yield return या आलसी कार्यान्वयन के लिए लिंक ऑपरेटर का उपयोग करने की अनुमति मिलती है।

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

0

ऐरे हानिकारक है, लेकिन ICollection<T> भी हानिकारक है।

ICollection<T> इस बात की गारंटी नहीं दे सकता कि वस्तु अपरिवर्तनीय होगी।

मेरे सिफारिश ReadOnlyCollection<T>

12
साथ लौटने वस्तु रैप करने के लिए

एक IEnumerable<T> लौटें एक yield return का उपयोग कर रहा है।

+0

दिलचस्प सुझाव, मैंने कभी भी उस बारे में सोचा नहीं। –

+0

मैं इसे बहुत उपयोग करना शुरू कर रहा हूं, और यह वास्तव में LINQ के साथ कुछ वास्तव में सुरुचिपूर्ण कोड बनाता है। –

+0

+1 जब तक आप "उपज रिटर्न का उपयोग नहीं करते" तब तक मैं सहमत नहीं था। इटरेटर ब्लॉक एक बहुत ही शक्तिशाली उपकरण हैं, यदि सही तरीके से उपयोग किया जाता है, तो आपके कोड और आपकी मेमोरी पदचिह्न को व्यवस्थित कर सकते हैं। –

8

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

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

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


संपादित करें (मोनोऑक्साइड): यह बाद से सवाल की तरह नहीं दिखता बंद कर दिया जा रहा है हो सकता है, मैं तो बस इस बारे में अन्य प्रश्न से एक लिंक जोड़ना चाहते हैं: Why arrays are harmful

+0

अच्छी तरह से कहा। – Shog9

1

यह निर्भर करता है जिस संग्रह पर आप लौट रहे हैं उसके साथ आप क्या करना चाहते हैं।यदि आप बस पुनरावृत्त कर रहे हैं, या यदि आप केवल उपयोगकर्ता को फिर से चालू करना चाहते हैं, तो मैं @Daniel से सहमत हूं, IEnumerable<T> लौटाएं। यदि आप वास्तव में सूची-आधारित संचालन की अनुमति देना चाहते हैं, तो मैं IList<T> वापस कर दूंगा।

5

सलाह है कि मैं बार बार उद्धृत सुना है का एक अच्छा टुकड़ा यह है:

, तुम क्या स्वीकार में उदार आप क्या प्रदान में सटीक हो।

अपने एपीआई को डिजाइन करने के मामले में, मैं सुझाव दूंगा कि आपको एक इंटरफ़ेस लौटाया जाना चाहिए, ठोस प्रकार नहीं।

अपने उदाहरण विधि ले रहा है, मैं इसे इस प्रकार पुनर्लेखन चाहते हैं:

public IList<object> Foo() 
{ 
    List<object> retList = new List<object>(); 
    // Blah, blah, [snip] 
    return retList; 
} 

महत्वपूर्ण यह है कि अपने आंतरिक कार्यान्वयन विकल्प है - एक सूची का उपयोग करने के लिए - फोन करने वाले को पता चला नहीं है, लेकिन आप कर रहे हैं एक उपयुक्त इंटरफ़ेस लौट रहा है।

फ्रेमवर्क विकास पर माइक्रोसॉफ्ट के अपने दिशानिर्देश विशिष्ट प्रकारों को वापस करने, इंटरफेस के पक्ष में सिफारिश करने के खिलाफ अनुशंसा करते हैं। (क्षमा करें, मुझे इसके लिए कोई लिंक नहीं मिला)

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

फिर से अपने उदाहरण विधि ले रहा है:

public IList<object> Foo(IEnumerable<object> bar) 
{ 
    List<object> retList = new List<object>(); 
    // Blah, blah, [snip] 
    return retList; 
} 
संबंधित मुद्दे

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