2011-03-01 10 views
22

कई परियोजनाओं पर काम करते हैं मैं, जब भी मैं एक रीड ओनली संग्रह वापस लौटाना होगा में, मैं IEnumerable<T> इंटरफ़ेस का उपयोग और कर ऐसा जैसे विशिष्ट टाइप करें:क्या मुझे IENumerable <T> या Arrays का पक्ष लेना चाहिए?

Public ReadOnly Property GetValues() As IEnumerable(Of Integer) 
    Get 
     'code to return the values' 
    End Get 
End Property 

अधिकांश समय, मैं एक सूची लौट लेकिन में कुछ फ़ंक्शंस और केवल गुणों को पढ़ते हैं, मैं एक सरणी लौटाता हूं जो विस्तार विधियों की दयालुता से ठीक से उद्देश्य को पूरा करता है।

मेरा प्रश्न है मैं किसी भी डिजाइन सिद्धांतों लौटने IEnumerable<T> बजाय विशिष्ट प्रकार के द्वारा उल्लंघन करने कर रहा हूँ (उदा .: List<T>, HashSet<T>, Stack<T> या Array रों)?

+1

http://stackoverflow.com/questions/3433284/ienumerablet-vs-t – Alex

उत्तर

28

मैं आम तौर पर IEnumerable<T> पसंद करता हूं। मुख्य बात यह है कि खुद से पूछना है कि विधि से वास्तविक (यहां तक ​​कि न्यूनतम) कार्यक्षमता वापस आ रही है (या विधि तर्क के मामले में इसे पास किया गया है)।

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

+8

क्या यह जोखिम भरा नहीं है, जब सरणी की तुलना में, यह 'आईनेमरेबल' तत्वों तक पहुंचने के लिए कुछ निष्पादन छुपाया जा सकता है जबकि '[]' कभी नहीं होगा? अर्थात। क्या स्थगित निष्पादन के संभावित दुष्प्रभाव कुछ हद तक लाभ से अधिक हैं? –

+2

सरणी के पास उनके सूचकांक पर कोड भी है – user1496062

0

यदि आपको List<T>, HashSet<T> आदि द्वारा प्रदान की गई अतिरिक्त सुविधाओं की आवश्यकता नहीं है तो IEnumerable<T> लौटाना ठीक है, इमो।

जो कुछ भी आपको लगता है उसे लौटाना सबसे उपयुक्त है; यदि आपको केवल संग्रहों पर लूप करने की आवश्यकता है या उनके साथ LINQ-y सामान करें तो IEnumerable<T> अधिकांश स्थितियों में अच्छा है।

जब आप वापस जाने के लिए की आवश्यकता है "अमीर" प्रकार तो बल्कि एक ठोस प्रकार की तुलना में एक अंतरफलक लौटने पर विचार - IList<T> बल्कि List<T> से, ISet<T> बल्कि HashSet<T> से आदि - ताकि आपके कार्यान्वयन यदि आवश्यक हो, भविष्य में बदल सकते हैं, किसी भी कॉलिंग कोड तोड़ने के बिना।

2

IEnumerable<T> लौटने पर ठीक है। हालांकि यह देखें कि यदि टी संदर्भ प्रकार है तो कॉलर के लिए ऑब्जेक्ट को संशोधित करना संभव है।

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

0

यह निर्भर करता है। यदि आप अपनी विधि का उपयोग करना चाहते हैं तो केवल गणना है, तो IENumerable सही विकल्प है।

यदि इंडेक्स लुकअप जैसी विशिष्ट सुविधाएं महत्वपूर्ण हैं, तो आप अधिक विशिष्ट हो सकते हैं।

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

+4

आपका अंतिम पैराग्राफ कोई समझ नहीं आता है ... – Domenic

+1

आप हमेशा एक गणना पर ToList या ToArray LINQ एक्सटेंशन को कॉल कर सकते हैं। एक चालाक कंपाइलर सूची या सरणी पीढ़ी को बाईपास कर सकता है अगर स्रोत गणना स्वयं एक सूची/सरणी है और उपयोग के अर्थशास्त्र इसे अनुमति देता है (सूची संशोधित नहीं है)। – Holstebroe

3

यह इस बात पर निर्भर करता है कि आप क्या करना चाहते हैं और आप "उल्लंघन" का इरादा रखते हैं। यह निर्भर करता है से:

  1. आप अपने संग्रह चाहते हैं अपने वस्तुओं द्वारा वापस बाहर कोड द्वारा किसी भी किसी और जो संशोधन की अनुमति बदला जा सकता है, तो आप चाहिए रिटर्न सूची <>, HashSet <> उर्फ ​​परिवर्तनीय प्रकार स्टैक <> या
  2. आप अपने "संग्रह उपयोगकर्ता" बस संग्रह वस्तुओं पर लेकिन संग्रह खुद को संशोधित किए बिना पुनरावृति करना चाहते हैं, यह सही चुनाव को ध्यान में

लें कि कई अच्छे डिजाइन गुरु और सिद्धांतों IEnumerable वापस जाने के लिए पसंद करते हैं <> संशोधित-संग्रह-तैयार

17

डेविड का उत्तर काफी अधिक इसमें शामिल है; IEnumerable<T> सामान्य रूप से सर्वोत्तम अभ्यास है। आप इसे नए फ्रेमवर्क विधियों को देखकर देख सकते हैं।

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

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

0

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

12

व्यक्तिगत रूप से मुझे लगता है कि एक एपीआई से IEnumerable<T> लौटने का एक मजबूत संकेत है कि कार्यान्वयन आलसी मूल्यांकन का उपयोग कर सकता है।

कि आलसी मूल्यांकन फोन करने वाले के लिए महत्वपूर्ण हो सकता है इस्तेमाल किया जा सकता को जानने का है, इसका मतलब है कि:

  • परिणाम पर पुनरावृत्ति एक बार से अधिक (जैसे गिनती प्राप्त करने के लिए तो डेटा का उपयोग) परिणाम होगा मूल्यांकन में एक से अधिक बार किया जा रहा है।

  • अपवाद एपीआई से फेंकी जा सकती है परिणाम पर पुनरावृत्ति करते हुए:

उदा

IEnumerable<MyObject> LazyEvaluatedApi() 
{ 
} 

... 

IEnumerable<MyObject> result = LazyEvaluatedApi(); 
... 
foreach(MyObject item in result) // Exception from LazyEvaluatedApi may be thrown here. 
{ 
} 

आपको नहीं लगता कि किसी भी कार्यान्वयन आलसी मूल्यांकन (उदाहरण के लिए डेटा एक्सेस परत एपीआई) का उपयोग करने की आवश्यकता होगी है, तो मुझे ICollection<T> या IList<T> वापस जाने के लिए पसंद करेंगे। कॉलर को Count संपत्ति (ICollection<T> और IList<T>) और एक इंडेक्सर (IList<T> केवल) तक पहुंच प्रदान करने के अलावा, आप यह भी स्पष्ट रूप से संकेत दे रहे हैं कि कोई आलसी मूल्यांकन नहीं होगा।

अपने ICollection<T> या IList<T> लौटने पर, आपका ठोस कार्यान्वयन आमतौर पर List<T> लौटाएगा। यदि यह महत्वपूर्ण है कि सूची केवल पढ़ने के लिए है, तो List<T>.AsReadOnly()

+0

अच्छा जवाब। उस संदर्भ में, मैंने कभी नहीं समझा है कि ईएफ नेविगेशन गुणों का उपयोग क्यों किया जाता है [ICollection ] (https://msdn.microsoft.com/en-us/library/92t2ye13 (v = vs.110) .aspx)। – Chalky

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

  • कोई संबंधित समस्या नहीं^_^