मुझे IEnumerable <T> पर सूची <T> का उपयोग क्यों करना चाहिए?


24

मेरे ASP.net MVC4 वेब एप्लिकेशन में मैं IEnumerables का उपयोग करता हूं, इंटरफ़ेस को प्रोग्राम करने के लिए मंत्र का पालन करने की कोशिश कर रहा हूं, कार्यान्वयन नहीं।

Return IEnumerable(Of Student)

बनाम

Return New List(Of Student)

लोग मुझे सूची का उपयोग करने के लिए कह रहे हैं न कि IEnumerable का उपयोग करने के लिए, क्योंकि सूची क्वेरी को निष्पादित करने के लिए मजबूर करती है और IEumerable नहीं करता है।

क्या यह वास्तव में सबसे अच्छा अभ्यास है? क्या कोई विकल्प है? मुझे ठोस वस्तुओं का उपयोग करने में अजीब लगता है जहां एक इंटरफ़ेस का उपयोग किया जा सकता है। क्या मेरी अजीब भावना उचित है?


2
एर, पहले, क्वेरी को निष्पादित करने के लिए मजबूर करना एक अच्छी बात क्यों है? दूसरा, आपको यह देखने के लिए डेटाबेस कॉल की निगरानी और प्रोफाइलिंग करनी चाहिए कि क्या इस तकनीकी विचार में कोई योग्यता है या नहीं।
user16764

2
यह कहा जाता है कि सभी प्रश्नों को निष्पादित किया जाना चाहिए ताकि मॉडल किया जाए और दृश्य के लिए तैयार लोड हो। यानी दृश्य सब कुछ प्राप्त करना चाहिए और डेटाबेस को क्वेरी नहीं करना चाहिए।
रोवन फ्रीमैन

3
यह StackOverflow प्रश्न इसे बहुत अच्छी तरह से कवर करता है।
कार्ल बेवेलफेल्ट

यह एक अच्छा जवाब है, लेकिन मैं यह जानना चाहता हूं कि यह एमवीसी की प्रासंगिकता है। दृश्य को IEnumerables क्यों नहीं दिया जा सकता है ताकि सभी प्रश्न बस समय में चलें?
रोवन फ्रीमैन

2
"यह कहा गया है कि सभी प्रश्नों को निष्पादित किया जाना चाहिए ताकि मॉडल किया जाए और दृश्य के लिए तैयार लोड किया जाए। यानी दृश्य को सब कुछ प्राप्त करना चाहिए और डेटाबेस को क्वेरी नहीं करना चाहिए।" यह बकवास है। यदि आप एक IEnumerable पास करते हैं, तो आपके विचार को पता नहीं है या परवाह नहीं है कि क्या यह डेटाबेस को क्वेरी कर रहा है। और यही तरीका होना चाहिए।
user16764

जवाबों:


21

ऐसे समय होते हैं, जब ToList()आपके प्रश्नों पर उस समय और जिस क्रम में आप उनसे अपेक्षा करते हैं, उस पर अमल सुनिश्चित करने के लिए आपके लिनक प्रश्नों को करना महत्वपूर्ण हो सकता है। वे परिदृश्य हालांकि दुर्लभ हैं और किसी को भी बहुत चिंता नहीं करनी चाहिए जब तक कि वे वास्तव में उनमें भाग न लें।

लंबी कहानी छोटी, IEnumerableकभी भी आपको केवल पुनरावृत्ति की आवश्यकता है, का उपयोग करें IListजब आपको सीधे अनुक्रमित करने की आवश्यकता होती है और एक गतिशील आकार के सरणी की आवश्यकता होती है (यदि आपको निश्चित आकार के सरणी पर अनुक्रमण की आवश्यकता है तो बस एक मानक सरणी का उपयोग करें)।

निष्पादन समय की बात के लिए, आप हमेशा एक IEnumerableचर के रूप में एक सूची का उपयोग कर सकते हैं , इसलिए स्वतंत्र रूप से एक निष्पादन IEnumerableकरके वापस लौटने के लिए स्वतंत्र महसूस करें .ToList();, या एक पैरामीटर के रूप में पारित IEnumerableकरने .ToList()के IEnumerableलिए निष्पादित करने के लिए सही है और उसके बाद। बस इस बात का ध्यान रखें कि जब भी आप निष्पादन के लिए बाध्य .ToList()करते हैं, तो उस IEnumerableचर पर न टांगें जो आपने अभी-अभी किया है और इसे फिर से निष्पादित करें, अन्यथा आप अपनी LINQ क्वेरी में पुनरावृत्तियों को अनावश्यक रूप से दोगुना कर देंगे।

एमवीसी के संबंध में, यहां ध्यान देने योग्य कुछ खास नहीं है। यह .NET के बाकी नियमों के अनुसार ही निष्पादन समय नियमों का पालन करने वाला है, मुझे लगता है कि आपके पास कोई ऐसा व्यक्ति हो सकता है जो अतीत में विलंबित निष्पादन शब्दार्थ के कारण भ्रम की स्थिति में था और उसने एमवीसी पर यह आरोप लगाते हुए कहा कि यह किसी तरह से संबंधित है, लेकिन यह है नहीं। विलंबित निष्पादन शब्दार्थ पहले सभी को भ्रमित करता है (और बाद में एक अच्छे के लिए भी; वे एक स्पर्श के रूप में हो सकते हैं)। फिर भी, बस इसके बारे में चिंता न करें जब तक आप वास्तव में यह सुनिश्चित करने के बारे में परवाह नहीं करते हैं कि LINQ क्वेरी दो बार निष्पादित नहीं होती है या इसे किसी अन्य कोड के सापेक्ष एक निश्चित क्रम में निष्पादित करने की आवश्यकता होती है, जिस बिंदु पर अपना चर स्वयं को असाइन करें। निष्पादन को मजबूर करने के लिए और आप ठीक हो जाएंगे।


क्या IEnumerables को देखने के लिए बुरा है? क्या आपको इसे सूचियाँ देनी चाहिए ताकि प्रश्नों को उस समय तक निष्पादित किया जा सके जब तक कि दृश्य उन्हें प्राप्त न हो जाए?
रोवन फ्रीमैन

@RowanFreeman मैंने इसका उत्तर देने के लिए केवल एक संपादन जोड़ा है। मुझे लगता है कि आप किसी ऐसे व्यक्ति से मिल गए हैं, जो पूरी तरह से समझ में नहीं आया (उन्हें दोष नहीं दे सकता है, देरी से क्रियान्वयन गंभीर रूप से जटिल और भ्रामक है) और विलंबित निष्पादन के पूर्ण व्यवहार को समझने के लिए काम करने के बजाय इसे खराब joojoo तक चलाया गया। अर्थ विज्ञान।
जिमी होफा

अच्छा जवाब। तो क्या मुझे वास्तव में उपयोग करने की आवश्यकता होगी। ToList ()? अब तक मेरा आवेदन केवल IEnumerables का उपयोग करके और उन्हें मॉडल से दृश्य में पास करने के लिए ठीक काम करता है। कोई सूची या .TLList () नहीं। मेरा प्रश्न कार्यक्षमता में से एक नहीं है - मुझे पता है कि मेरा आवेदन काम करता है। मेरा प्रश्न सर्वश्रेष्ठ अभ्यास में से एक है।
रोवन फ्रीमैन

4
@RowanFreeman सबसे अच्छा अभ्यास न्यूनतम इंटरफ़ेस का उपयोग करना है जो अभी भी आपकी आवश्यकताओं को पूरा करता है। IEnumerable आपके लिए अभी यह कर रहा है इसलिए इसे बदलने के बारे में चिंता न करें। उसने कहा, एक दिन आएगा जब आप एक क्वेरी को 3 या 10 बार निष्पादित करेंगे और समझ नहीं पाएंगे कि क्यों, या एक क्वेरी को निष्पादित करने की अपेक्षा एक सम्मिलित करने से पहले इसे निष्पादित करने के लिए खोजने के बाद, ये ऐसे समय हैं जिन्हें आपको पहचानने की आवश्यकता है। () जब आप चाहते हैं तो निष्पादन को मजबूर कर देगा, और कई बार एक LINQ क्वेरी से IEnumerable को दोहराते हुए, पूरे क्वेरी को कई बार निष्पादित करेगा; उन घटनाओं के होने पर अपने निष्पादन को ठीक करें
जिमी हॉफ

1
तुम भी उपयोग नहीं करना चाहिए Listएक के आसपास --passing Listका तात्पर्य है कि सूची की सामग्री को संशोधित किया जा जा रहे हैं। यदि आप एक संग्रह वापस करना चाहते हैं, तो उपयोग करें IReadOnlyCollectionListविधियों के भीतर उपयोग के लिए है, और सूची को संशोधित करने वाले तरीकों के बीच आदान-प्रदान के लिए है। बस!
एरिक

7

दो मुद्दे हैं।

IENumerable<Data> query = MyQuery();

//Later
foreach (Data item in query) {
  //Process data
}

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

एक द्वितीयक समस्या यह है कि "प्रोसेस डेटा" लूप पूरा होने तक आपका कनेक्शन जारी नहीं किया जाएगा। यह केवल एक समस्या है अगर "प्रोसेस डेटा" जटिल है। यह http://msdn.microsoft.com/en-us/library/bb386929.aspx पर उल्लिखित है :

Q. मेरा डेटाबेस कनेक्शन कब तक खुला रहता है?

A. जब तक आप क्वेरी परिणामों का उपभोग नहीं करते तब तक एक कनेक्शन खुला रहता है। यदि आप सभी परिणामों को संसाधित करने के लिए समय लेने की उम्मीद करते हैं और परिणामों को कैशिंग करने का विरोध नहीं कर रहे हैं, तो प्रश्न के लिए ToList लागू करें। सामान्य परिदृश्यों में, जहाँ प्रत्येक वस्तु को केवल एक बार संसाधित किया जाता है, स्ट्रीमिंग मॉडल DataReader और LINQ से SQL दोनों में श्रेष्ठ है।

इसलिए, ये मुद्दे हैं कि आपको यह सुनिश्चित करने के लिए प्रोत्साहित क्यों किया जा रहा है कि क्वेरी वास्तव में निष्पादित की जाती है, जैसे कॉल करके ToList()। हालाँकि, जिमी के रूप में यह दर्शाता है कि आपकी सूची को IEnumerable के रूप में वापस करने से कुछ भी नहीं है।

एक सामान्य नियम के रूप में, मैं एक से अधिक बार IEnumerable पर चलने से बचने की सलाह देता हूं। आपके कोड के उपभोक्ताओं को इस नियम का पालन करते हुए, मुझे यह चिंता नहीं है कि कोई व्यक्ति दो बार क्वेरी को निष्पादित करके डेटाबेस को हिट कर सकता है।


1

IEnumerableप्रारंभिक गणना करने का एक और लाभ यह है कि उपयुक्त स्थान पर फेंक दिया जाएगा। यह डिबगिंग का समर्थन करता है।

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


IEnumerableफेंकने वाला कोई भी तरीका शायद गलती कर रहा है। आस्थगित IEnumerableविधियों को दो में विभाजित किया जाना चाहिए: एक गैर-आस्थगित विधि मापदंडों की जांच करती है और सेट करती है, यदि आवश्यक हो तो फेंक दें (कहते हैं, अशक्त तर्क के कारण)। तो फिर यह निजी कार्यान्वयन जो के लिए एक कॉल देता है टाल। मुझे नहीं लगता कि मेरी टिप्पणियाँ आपके उत्तर के साथ पूरी तरह से हैं, लेकिन क्या आपको लगता है कि आपने अपने उत्तर में एक महत्वपूर्ण पहलू छोड़ दिया है, जो कि बनाम ए (म्यूटेशन) बनाम (कोई लाभ नहीं ) का उपयोग करने का अर्थ है आघात)IEnumerableListIReadOnlyCollection
एरिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.