LINQ प्रश्नों में ToList () या ToArray () को कॉल करना बेहतर है?


518

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

string raw = "...";
var lines = (from l in raw.Split('\n')
             let ll = l.Trim()
             where !string.IsNullOrEmpty(ll)
             select ll).ToList();

यह ठीक काम करता है। लेकिन अगर मैं परिणाम को संशोधित नहीं करने जा रहा हूं, तो मैं ToArray()इसके बजाय कॉल कर सकता हूं ToList()

मुझे आश्चर्य है कि क्या ToArray()पहले कॉलिंग द्वारा लागू किया गया है ToList()और इसलिए यह केवल कॉल करने की तुलना में कम स्मृति कुशल है ToList()

मैं पागल हो रहा हूँ? क्या मुझे सिर्फ ToArray()यह कहना चाहिए - सुरक्षित और सुरक्षित इस ज्ञान में कि स्मृति को दो बार आवंटित नहीं किया जाएगा?


10
यदि आप कभी भी यह जानना चाहते हैं कि .NET में पर्दे के पीछे क्या होता है, तो मैं वास्तव में .NET रिफ्लेक्टर सुझाता
डेविड हेडलंड

32
@DavidHedlund मैं .net स्रोत कोड सुझाता हूं ।
गक्क्निबग्ग

1
मैं इस बात से सहमत नहीं हूं कि stackoverflow.com/questions/6750447/c-toarray-performance इस प्रश्न का एक डुप्लिकेट है, भले ही एक महत्वपूर्ण संबंध हो। दोनों मेमोरी उपयोग (यह सवाल) और प्रदर्शन (अन्य प्रश्न) और दिलचस्प और अनौपचारिक विचार हैं। उन्हें अलग से वर्णित किया जा सकता है, लेकिन दोनों को एक दूसरे को चुनने का निर्णय लेना चाहिए। मैं इस या अन्य प्रश्न के उत्तर में से किसी एक की भी सिफारिश नहीं कर सकता। कई जवाब हैं कि जब एक साथ लिया जाता है तो एक दूसरे पर एक का चयन करने के तरीके की पूरी चर्चा प्रदान करते हैं।
चरण

1
@Gqqnbig - सबसे उपयोगी टिप्पणी कभी भी! धन्यवाद :-)
मार्क कूपर

जवाबों:


365

जब तक आपको बस अन्य बाधाओं को पूरा करने के लिए एक सरणी की आवश्यकता होती है, जिसका आपको उपयोग करना चाहिए ToList। परिदृश्य के बहुमत में ToArrayअधिक से अधिक स्मृति आवंटित करेगा ToList

दोनों भंडारण के लिए सरणियों का उपयोग करते हैं, लेकिन ToListअधिक लचीला बाधा है। यह संग्रह में तत्वों की संख्या के रूप में कम से कम बड़े होने के लिए सरणी की आवश्यकता है। यदि सरणी बड़ा है, तो यह कोई समस्या नहीं है। हालांकि ToArrayतत्वों की संख्या के लिए सरणी का आकार ठीक होना चाहिए।

इस बाधा को पूरा करने के लिए ToArrayअक्सर एक से अधिक आवंटन करते हैं ToList। एक बार जब यह एक सरणी होता है जो काफी बड़ा होता है तो यह एक सरणी आवंटित करता है जो बिल्कुल सही आकार है और तत्वों को उस सरणी में वापस कॉपी करता है। इससे बचने का एक ही समय है जब सरणी के लिए ग्रोथ एल्गोरिथ्म बस संग्रहीत होने की आवश्यकता वाले तत्वों की संख्या के साथ मेल खाता है (निश्चित रूप से अल्पसंख्यक में)।

संपादित करें

कुछ लोगों ने मुझे List<T>मूल्य में अतिरिक्त अप्रयुक्त स्मृति होने के परिणाम के बारे में पूछा है ।

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

सामान्य तौर पर हालांकि मुझे यह दुर्लभ मामला लगता है। यह बहुत अधिक ToArrayकॉल को देखने के लिए बहुत आम है जो तुरंत स्मृति के अन्य अल्पकालिक उपयोगों के लिए पारित हो जाते हैं जिसमें मामले ToListका प्रदर्शन बेहतर होता है।

यहाँ कुंजी प्रोफ़ाइल, प्रोफ़ाइल और फिर प्रोफ़ाइल कुछ और है।


14
दूसरी ओर, एरे बनाने के लिए जो अतिरिक्त मेमोरी आवंटित की जाती है वह एरे को कचरा संग्रहण के लिए योग्य नहीं होगी, जबकि सूची के लिए अतिरिक्त ओवरहेड रहेगा? मैं कहता हूं कि इसे सरल बनाए रखें। यदि आपको तत्वों को जोड़ने या निकालने की आवश्यकता है, तो उसके लिए एक उपकरण है। यदि आप नहीं करते हैं, तो उसके लिए एक अलग उपकरण है। जो समझ में आता है, उसका उपयोग करें। यदि बाद में, आप स्मृति और प्रदर्शन के साथ एक समस्या की खोज करते हैं, और यह वह है , इसे बदलें।
एंथनी पेग्राम

1
@AnthonyPegram हाँ जो बनाने के लिए एक वैध विचार है। यदि मूल्य का उपयोग लंबी अवधि के भंडारण में किया जा रहा है, तो इसे संशोधित नहीं किया जाएगा, और संभावित रूप से इसे जनरल 2 में बना देगा तो आप अतिरिक्त आवंटन का भुगतान करने से बेहतर हो सकते हैं और अब जनरल 2 ढेर को प्रदूषित कर सकते हैं। IME हालांकि मैं शायद ही कभी यह देखता हूं। यह देखने के लिए बहुत अधिक सामान्य है कि ToArray को तुरंत एक और अल्पकालिक LINQ क्वेरी में पारित किया जाए।
जरीदपार

2
@AnthonyPegram मैंने चर्चा के इस पक्ष को शामिल करने के लिए अपना जवाब अपडेट किया
जारेदपैर

8
@JaredPar मुझे समझ में नहीं आता है कि कैसे ToArrayअधिक मेमोरी आवंटित की जा सकती है अगर इसे सटीक स्थानों के आकार की आवश्यकता है जहां ToList<>जाहिर है कि यह स्वचालित स्पेयर स्थान है। (ऑटोइनक्रीज)
रॉय नमिर

5
@RoyiNamir क्योंकि ToArray पहले ओवरहेड के साथ ToList- शैली का आवंटन करता है, फिर एक अतिरिक्त सटीक आकार का आवंटन करता है।
टिम्बो

169

प्रदर्शन अंतर नगण्य होगा, क्योंकि List<T>एक गतिशील आकार सरणी के रूप में कार्यान्वित किया जाता है। या तो कॉल करना ToArray()(जो Buffer<T>कि सरणी को विकसित करने के लिए एक आंतरिक वर्ग का उपयोग करता है ) या ToList()(जिसे List<T>(IEnumerable<T>)निर्माणकर्ता कहते हैं ) अंत में उन्हें एक सरणी में रखने और सरणी बढ़ने तक बात होगी जब तक कि यह उन सभी को फिट नहीं करता है।

यदि आप इस तथ्य की ठोस पुष्टि की इच्छा रखते हैं, तो रिफ्लेक्टर में प्रश्न में विधियों के कार्यान्वयन की जांच करें - आप देखेंगे कि वे लगभग समान कोड के लिए उबलते हैं।


2
एक दिलचस्प तथ्य जो मेरे सामने आया, वह यह है कि समूह के माध्यम से परिभाषित समूह के उपयोग से होने वाले सहसंबद्ध प्रश्नों के कारण आपके प्रक्षेपण में शामिल होने के कारण लाइनक उस समूह के लिए गणना को पुनः प्राप्त करने के लिए एक अन्य उप-क्वेरी को जोड़ने के लिए एसक्यूएल को जोड़ देता है। मैं यह मान रहा हूं कि इन मामलों में इसका मतलब है कि संग्रह का आकार आइटम पुनर्प्राप्त होने से पहले ज्ञात होगा और इस प्रकार एक सटीक आकार सरणी सीधे बनाया जा सकता है जो परिणामों को भौतिक करते समय प्रसंस्करण और मेमोरी संसाधनों पर बचत करेगा।
जिपरसन

133
यदि गणना पहले से ज्ञात है, तो प्रदर्शन समान है। हालाँकि, यदि गिनती पहले से ज्ञात नहीं है, तो केवल इतना ही अंतर है ToArray()और ToList()यह है कि पूर्व को अतिरिक्त ट्रिम करना होगा, जिसमें संपूर्ण सरणी की प्रतिलिपि बनाना शामिल है, जबकि बाद वाला अतिरिक्त ट्रिम नहीं करता है, लेकिन औसत 25 का उपयोग करता है % अधिक स्मृति। यह केवल निहितार्थ होगा यदि डेटा प्रकार एक बड़ा है struct। सिर्फ विचार के लिए भोजन।
स्कॉट रिप्पी

9
@EldritchConundrum 25% इस तर्क से आता है: यदि वस्तुओं की संख्या अज्ञात है, तो कॉलिंग ToListया ToArrayएक छोटा बफर बनाकर शुरू होगा। जब वह बफर भर जाता है, तो वह बफर की क्षमता को दोगुना कर देता है और जारी रहता है। चूंकि क्षमता हमेशा दोगुनी होती है, अप्रयुक्त बफर हमेशा 0% और 50% के बीच होगा।
स्कॉट रिप्पी

2
@ ScottRippey मैंने अभी IEnumerable स्रोत से नई सूची के स्रोत को देखा, और यह जाँचता है कि क्या IEnumerable एक ICollection है, और यदि यह है, तो यह गणना गुण से आवश्यक सटीक आकार के साथ एक सरणी आवंटित करके शुरू होता है, इसलिए यह ऐसा होगा जहां टोललिस्ट () निश्चित रूप से तेज होगा। एक पूर्ण उत्तर में यह तथ्य शामिल हो सकता है, हालांकि मुझे नहीं लगता कि यह सबसे सामान्य मामला है।
एंडीक्लाव

3
@AndyClaw दोनों Listऔर Bufferजांच करेंगे ICollectionकि किस स्थिति में प्रदर्शन समान होगा।
स्कॉट रिपी

54

(सात साल बाद ...)

अन्य (अच्छे) उत्तरों के एक जोड़े ने सूक्ष्म प्रदर्शन अंतरों पर ध्यान केंद्रित किया है जो घटित होंगे।

यह पद एक सरणी द्वारा उत्पादित ( ) के रूप में एक के द्वारा दिए गए की तुलना में उत्पन्न शब्दार्थ के बीच मौजूद सिमेंटिक अंतर का उल्लेख करने के लिए सिर्फ एक पूरक है ।IEnumerator<T>T[]List<T>

उदाहरण के साथ सचित्र:

IList<int> source = Enumerable.Range(1, 10).ToArray();  // try changing to .ToList()

foreach (var x in source)
{
  if (x == 5)
    source[8] *= 100;
  Console.WriteLine(x);
}

उपरोक्त कोड बिना किसी अपवाद के चलेगा और आउटपुट उत्पन्न करेगा:

1
2
3
4
5
6
7
8
900
10

यह दिखाता है कि IEnumarator<int>एक द्वारा दिया int[]कि क्या सरणी प्रगणक के निर्माण के बाद से संशोधित किया गया है पर हिसाब नहीं रखता।

ध्यान दें कि मैंने स्थानीय चर sourceको a घोषित किया है IList<int>। इस तरह से मुझे यकीन है कि C # कंपाइलर foreachस्टेटमेंट को किसी ऐसी चीज में ऑप्टिमाइज़ नहीं करता है जो for (var idx = 0; idx < source.Length; idx++) { /* ... */ }लूप के बराबर है । अगर मैं var source = ...;इसके बजाय इसका उपयोग करूं तो C # कंपाइलर ऐसा कर सकता है । .NET फ्रेमवर्क के मेरे वर्तमान संस्करण में यहां उपयोग किया गया वास्तविक एन्यूमरेटर एक गैर-सार्वजनिक संदर्भ-प्रकार है, System.SZArrayHelper+SZGenericArrayEnumerator`1[System.Int32]लेकिन निश्चित रूप से यह एक कार्यान्वयन विवरण है।

अब, अगर मैं बदल .ToArray()में .ToList(), मैं सिर्फ मिलती है:

1
2
3
4
5

इसके बाद एक System.InvalidOperationExceptionझटका अप ने कहा:

संग्रह को संशोधित किया गया था; गणना संचालन निष्पादित नहीं हो सकता है।

इस मामले में अंतर्निहित प्रगणक सार्वजनिक परिवर्तनशील मूल्य-प्रकार है System.Collections.Generic.List`1+Enumerator[System.Int32]( IEnumerator<int>इस मामले में एक बॉक्स के अंदर बॉक्सिंग क्योंकि मैं उपयोग करता हूं IList<int>)।

अंत में, एनुमरेटर द्वारा बनाए गए एन्यूमरेटर इसList<T>बात पर नज़र रखता है कि सूची एन्यूमरेशन के दौरान बदलती है,T[]या नहींद्वारा बनाए गए एन्यूमरेटर। इसलिए इस अंतर पर विचार करें.ToList()औरबीच मेंसे चुनें.ToArray()

लोग अक्सर एक अतिरिक्त जोड़ते हैं .ToArray()या .ToList()एक संग्रह को दरकिनार करते हैं जो इस बात पर नज़र रखता है कि क्या यह एक एन्यूमरेटर के जीवन-काल के दौरान संशोधित किया गया था।

(किसी को भी जानना चाहता है तो कैसेList<> है कि क्या संग्रह संशोधित किया गया था पर ध्यान रखती है, वहाँ एक निजी क्षेत्र है _versionइस वर्ग जो हर बदल गया है में List<>अद्यतन किया जाता है।)


28

मैं @mquander से सहमत हूं कि प्रदर्शन अंतर नगण्य होना चाहिए। हालांकि, मैं इसे सुनिश्चित करने के लिए बेंचमार्क करना चाहता था, इसलिए मैंने किया - और यह नाकाफी है।

Testing with List<T> source:
ToArray time: 1934 ms (0.01934 ms/call), memory used: 4021 bytes/array
ToList  time: 1902 ms (0.01902 ms/call), memory used: 4045 bytes/List

Testing with array source:
ToArray time: 1957 ms (0.01957 ms/call), memory used: 4021 bytes/array
ToList  time: 2022 ms (0.02022 ms/call), memory used: 4045 bytes/List

प्रत्येक स्रोत सरणी / सूची में 1000 तत्व थे। इसलिए आप देख सकते हैं कि समय और स्मृति अंतर दोनों नगण्य हैं।

मेरा निष्कर्ष: जब तक आप वास्तव में कुछ बाइट्स आपके लिए मायने नहीं रखते, तब तक आप एक सूची की तुलना में अधिक कार्यक्षमता प्रदान करते हैं , क्योंकि आप ToList () का उपयोग कर सकते List<T>हैं।


1
मुझे आश्चर्य है कि यदि आप structएक आदिम प्रकार या वर्ग के बजाय एक बड़े का उपयोग करते हैं तो यह परिणाम अलग होगा ।
स्कॉट रिप्पी

12
सूची <T> .ToList ???? क्या चेतना है ? बेहतर यह एक IEnumerable में देने की कोशिश करेंगे, जो ICollection इंटरफ़ेस को लागू नहीं करता है।
ग्रिगरी

8
मैं यह सुनिश्चित करना चाहता था कि मैं केवल ToListया तो समय की माप कर रहा हूँ ToArrayऔर किसी की गणना नहीं कर रहा हूँ IEnumerable। सूची <T> .ToList () अभी भी एक नई सूची बनाता है <T> - यह "इसे वापस नहीं करता है"।
ईएमपी

23
-1 के व्यवहार ToArray()और ToList()बहुत ज्यादा अलग है जब वे एक साथ आपूर्ति की जाती ICollection<T>पैरामीटर - वे बस एक ही आवंटन और एक प्रति आपरेशन करते हैं। दोनों List<T>और Arrayकार्यान्वित ICollection<T>, इसलिए आपके मानक बिल्कुल भी मान्य नहीं हैं।
मोहम्मद देहघन

1
रुचि रखने वाले किसी व्यक्ति के लिए, मैंने एक अलग उत्तर के रूप में अपना स्वयं का बेंचमार्क पोस्ट किया । यह कार्यान्वयन की समस्या .Select(i => i)से बचने के लिए उपयोग करता ICollection<T>है, और इसमें एक नियंत्रण समूह भी शामिल है, यह देखने के लिए कि IEnumerable<>पहली बार में स्रोत पर चलने में कितना समय लगता है ।
स्ट्रिपिंगवर्यर

19

ToList()आम तौर पर पसंद किया जाता है यदि आप इसका उपयोग IEnumerable<T>(उदाहरण के लिए, ओआरएम से) करते हैं। यदि अनुक्रम की लंबाई शुरुआत में ज्ञात नहीं है, ToArray()तो सूची की तरह गतिशील-लंबाई संग्रह बनाता है और फिर इसे सरणी में परिवर्तित करता है, जिसमें अतिरिक्त समय लगता है।


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

5
ILSpy में देख रहा है, Enumerable.ToArray()कॉल करता है new Buffer<TSource>(source).ToArray()। बफर कंस्ट्रक्टर में यदि स्रोत ICollection को कार्यान्वित करता है, तो वह source.CopyTo (आइटम, 0 और उसके बाद .ToArray) को सीधे आंतरिक आइटम सरणी देता है। इसलिए कोई रूपांतरण नहीं है जो उस मामले में अतिरिक्त समय लेता है। यदि स्रोत ICollection को लागू नहीं करता है, तो ToArray एक सरणी प्रति में परिणाम देगा, जैसा कि स्कॉट Rippey की टिप्पणी द्वारा वर्णित सरणी के अंत से अतिरिक्त अप्रयुक्त स्थानों को ट्रिम करने के लिए है।
BrandonAGr

19

स्मृति को हमेशा दो बार आवंटित किया जाएगा - या उसके करीब कुछ। जैसा कि आप किसी सरणी का आकार नहीं बदल सकते हैं, दोनों विधियाँ बढ़ते संग्रह में डेटा को इकट्ठा करने के लिए किसी प्रकार के तंत्र का उपयोग करेंगी। (खैर, सूची अपने आप में एक बढ़ता हुआ संग्रह है।)

सूची किसी सरणी को आंतरिक संग्रहण के रूप में उपयोग करती है, और आवश्यकता होने पर क्षमता को दोगुना कर देती है। इसका मतलब यह है कि औसतन 2/3 वस्तुओं को कम से कम एक बार पुनः प्राप्त किया गया है, जिनमें से आधे को वास्तविक रूप से कम से कम दो बार, उन में से कम से कम तीन बार, और इसी तरह। इसका मतलब है कि प्रत्येक आइटम को औसत से 1.3 गुना घटाया गया है, जो बहुत अधिक उपरि नहीं है।

यह भी याद रखें कि यदि आप स्ट्रिंग्स एकत्र कर रहे हैं, तो संग्रह में केवल स्ट्रिंग्स के संदर्भ शामिल हैं, स्ट्रिंग्स स्वयं वास्तविक नहीं हैं।


यह पूछने के लिए एक अनभिज्ञ बात हो सकती है, लेकिन क्या आप 2/3, 1/3, 1/6 तर्क को रेखांकित नहीं करते हैं कि सूची की सरणी को जगह में बढ़ाया जा सकता है? अर्थात्, सरणी के अंत में खाली स्थान है ताकि मौजूदा आवंटन को स्थानांतरित करने की आवश्यकता न हो?

@JonofAllTrades: नहीं, सरणी को जगह में कभी नहीं बढ़ाया जाता है। .NET में मेमोरी प्रबंधन बस ऐसा नहीं करता है। यदि इसे जगह में बढ़ाया जाएगा, तो वस्तुओं के वास्तविककरण की कोई आवश्यकता नहीं होगी।
गुफ़ा १५’१३

आह, मैं देख रहा हूं: जिन वस्तुओं का पुन: आवंटन नहीं किया गया है, उन्हें ऐसा नहीं करना पड़ा क्योंकि वे अंतिम आवंटन में थे। पिछले आवंटन में आवंटित सभी आइटम स्थानांतरित हो गए हैं, लेकिन सरणी लंबाई में लॉगरिदमिक वृद्धि के कारण यह एक गणना योग्य अंश है। स्पष्टीकरण देने के लिए धन्यवाद!

19

यह बाहर 2020 है और हर कोई .NET कोर 3.1 का उपयोग कर रहा है, इसलिए मैंने बेंचमार्क .NET के साथ कुछ बेंचमार्क चलाने का फैसला किया।

TL; DR: ToArray () बेहतर प्रदर्शन-वार है और अगर आप कलेक्शन को म्यूट करने की योजना नहीं बना रहे हैं तो यह एक बेहतर काम है।


    [MemoryDiagnoser]
    public class Benchmarks
    {
        [Params(0, 1, 6, 10, 39, 100, 666, 1000, 1337, 10000)]
        public int Count { get; set; }

        public IEnumerable<int> Items => Enumerable.Range(0, Count);

        [Benchmark(Description = "ToArray()", Baseline = true)]
        public int[] ToArray() => Items.ToArray();

        [Benchmark(Description = "ToList()")]
        public List<int> ToList() => Items.ToList();

        public static void Main() => BenchmarkRunner.Run<Benchmarks>();
    }

परिणाम हैं:


    BenchmarkDotNet=v0.12.0, OS=Windows 10.0.14393.3443 (1607/AnniversaryUpdate/Redstone1)
    Intel Core i5-4460 CPU 3.20GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
    Frequency=3124994 Hz, Resolution=320.0006 ns, Timer=TSC
    .NET Core SDK=3.1.100
      [Host]     : .NET Core 3.1.0 (CoreCLR 4.700.19.56402, CoreFX 4.700.19.56404), X64 RyuJIT
      DefaultJob : .NET Core 3.1.0 (CoreCLR 4.700.19.56402, CoreFX 4.700.19.56404), X64 RyuJIT


    |    Method | Count |          Mean |       Error |      StdDev |        Median | Ratio | RatioSD |   Gen 0 | Gen 1 | Gen 2 | Allocated |
    |---------- |------ |--------------:|------------:|------------:|--------------:|------:|--------:|--------:|------:|------:|----------:|
    | ToArray() |     0 |      7.357 ns |   0.2096 ns |   0.1960 ns |      7.323 ns |  1.00 |    0.00 |       - |     - |     - |         - |
    |  ToList() |     0 |     13.174 ns |   0.2094 ns |   0.1958 ns |     13.084 ns |  1.79 |    0.05 |  0.0102 |     - |     - |      32 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |     1 |     23.917 ns |   0.4999 ns |   0.4676 ns |     23.954 ns |  1.00 |    0.00 |  0.0229 |     - |     - |      72 B |
    |  ToList() |     1 |     33.867 ns |   0.7350 ns |   0.6876 ns |     34.013 ns |  1.42 |    0.04 |  0.0331 |     - |     - |     104 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |     6 |     28.242 ns |   0.5071 ns |   0.4234 ns |     28.196 ns |  1.00 |    0.00 |  0.0280 |     - |     - |      88 B |
    |  ToList() |     6 |     43.516 ns |   0.9448 ns |   1.1949 ns |     42.896 ns |  1.56 |    0.06 |  0.0382 |     - |     - |     120 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |    10 |     31.636 ns |   0.5408 ns |   0.4516 ns |     31.657 ns |  1.00 |    0.00 |  0.0331 |     - |     - |     104 B |
    |  ToList() |    10 |     53.870 ns |   1.2988 ns |   2.2403 ns |     53.415 ns |  1.77 |    0.07 |  0.0433 |     - |     - |     136 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |    39 |     58.896 ns |   0.9441 ns |   0.8369 ns |     58.548 ns |  1.00 |    0.00 |  0.0713 |     - |     - |     224 B |
    |  ToList() |    39 |    138.054 ns |   2.8185 ns |   3.2458 ns |    138.937 ns |  2.35 |    0.08 |  0.0815 |     - |     - |     256 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |   100 |    119.167 ns |   1.6195 ns |   1.4357 ns |    119.120 ns |  1.00 |    0.00 |  0.1478 |     - |     - |     464 B |
    |  ToList() |   100 |    274.053 ns |   5.1073 ns |   4.7774 ns |    272.242 ns |  2.30 |    0.06 |  0.1578 |     - |     - |     496 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |   666 |    569.920 ns |  11.4496 ns |  11.2450 ns |    571.647 ns |  1.00 |    0.00 |  0.8688 |     - |     - |    2728 B |
    |  ToList() |   666 |  1,621.752 ns |  17.1176 ns |  16.0118 ns |  1,623.566 ns |  2.85 |    0.05 |  0.8793 |     - |     - |    2760 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |  1000 |    796.705 ns |  16.7091 ns |  19.8910 ns |    796.610 ns |  1.00 |    0.00 |  1.2951 |     - |     - |    4064 B |
    |  ToList() |  1000 |  2,453.110 ns |  48.1121 ns |  65.8563 ns |  2,460.190 ns |  3.09 |    0.10 |  1.3046 |     - |     - |    4096 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() |  1337 |  1,057.983 ns |  20.9810 ns |  41.4145 ns |  1,041.028 ns |  1.00 |    0.00 |  1.7223 |     - |     - |    5416 B |
    |  ToList() |  1337 |  3,217.550 ns |  62.3777 ns |  61.2633 ns |  3,203.928 ns |  2.98 |    0.13 |  1.7357 |     - |     - |    5448 B |
    |           |       |               |             |             |               |       |         |         |       |       |           |
    | ToArray() | 10000 |  7,309.844 ns | 160.0343 ns | 141.8662 ns |  7,279.387 ns |  1.00 |    0.00 | 12.6572 |     - |     - |   40064 B |
    |  ToList() | 10000 | 23,858.032 ns | 389.6592 ns | 364.4874 ns | 23,759.001 ns |  3.26 |    0.08 | 12.6343 |     - |     - |   40096 B |

    // * Hints *
    Outliers
      Benchmarks.ToArray(): Default -> 2 outliers were removed (35.20 ns, 35.29 ns)
      Benchmarks.ToArray(): Default -> 2 outliers were removed (38.51 ns, 38.88 ns)
      Benchmarks.ToList(): Default  -> 1 outlier  was  removed (64.69 ns)
      Benchmarks.ToArray(): Default -> 1 outlier  was  removed (67.02 ns)
      Benchmarks.ToArray(): Default -> 1 outlier  was  removed (130.08 ns)
      Benchmarks.ToArray(): Default -> 1 outlier  was  detected (541.82 ns)
      Benchmarks.ToArray(): Default -> 1 outlier  was  removed (7.82 us)

    // * Legends *
      Count     : Value of the 'Count' parameter
      Mean      : Arithmetic mean of all measurements
      Error     : Half of 99.9% confidence interval
      StdDev    : Standard deviation of all measurements
      Median    : Value separating the higher half of all measurements (50th percentile)
      Ratio     : Mean of the ratio distribution ([Current]/[Baseline])
      RatioSD   : Standard deviation of the ratio distribution ([Current]/[Baseline])
      Gen 0     : GC Generation 0 collects per 1000 operations
      Gen 1     : GC Generation 1 collects per 1000 operations
      Gen 2     : GC Generation 2 collects per 1000 operations
      Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
      1 ns      : 1 Nanosecond (0.000000001 sec)

1
यदि आप संग्रह को म्यूट करने की योजना नहीं बना रहे हैं, तो मुझे लगता है कि इरादे को बेहतर तरीके से दिखाया जा सकता है ToImmutableArray()(System.Collections.Immutable पैकेज से) uro
Arturo Torres SANchez

@ ArturoTorresSánchez सच है, लेकिन अगर संग्रह एक विधि के बाहर उजागर नहीं होता है, तो मैं सिर्फ एक सरणी का उपयोग करूंगा।
टायर्र्ज

2
इसके लिए धन्यवाद। चुना हुआ उत्तर एक मात्र तर्क है और उस तर्क के बाद परिणाम मानते हैं। वैज्ञानिक रूप से ऐसा करने के लिए और एक बोनस के रूप में पता है कि कितना अंतर है, यह जानने का केवल एक वास्तविक तरीका है।
जोनास

15

संपादित करें : इस उत्तर का अंतिम भाग मान्य नहीं है। हालांकि, बाकी अभी भी उपयोगी जानकारी है, इसलिए मैं इसे छोड़ दूँगा।

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन एक ही सवाल होने और कुछ शोध करने के बाद, मुझे कुछ दिलचस्प मिला है जो साझा करने लायक हो सकता है।

पहले, मैं @ उत्तर और उसके उत्तर से सहमत हूं। वह यह कहने में सही है कि प्रदर्शन-वार, दोनों समान हैं।

हालाँकि, मैं System.Linq.Enumerableविस्तार नामस्थान में विधियों पर एक नज़र डालने के लिए परावर्तक का उपयोग कर रहा हूँ, और मैंने एक बहुत ही सामान्य अनुकूलन पर ध्यान दिया है।
जब भी संभव हो, IEnumerable<T>स्रोत के लिए डाला जाता है IList<T>या ICollection<T>विधि अनुकूलन करने के लिए। उदाहरण के लिए, देखें ElementAt(int)

दिलचस्प बात यह है कि, Microsoft ने केवल ऑप्टिमाइज़ करने का विकल्प चुना IList<T>, लेकिन नहीं IList। ऐसा लगता है कि Microsoft IList<T>इंटरफ़ेस का उपयोग करना पसंद करता है।

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


16
मैंने एक परीक्षण किया और कुछ आश्चर्यजनक पाया। एक सरणी IList <T> को लागू करती है! सिस्टम का विश्लेषण करने के लिए परावर्तक का उपयोग करना। केवल इलिस्ट, ICollection, IEnumerable की एक वंशानुक्रम श्रृंखला का पता चलता है, लेकिन रन-टाइम प्रतिबिंब का उपयोग करके मुझे पता चला कि स्ट्रिंग [] में आईलिस्ट, आईसीएक्लेरेशन, IEnumerable, IList <string>, ICollection <string की विरासत श्रृंखला है। >, IEnumerable <string>। इसलिए, मेरे पास @mquander से बेहतर उत्तर नहीं है!
स्कॉट रिपी

@ScottRippey हां। आपके द्वारा देखा गया अजीब अवलोकन वास्तव में एक "हैक" का हिस्सा है - और इसमें कुछ निश्चित रूप से अजीब "निहित आकार" और इसी तरह के गुणों (आप इसे कैसे डालते हैं इसके आधार पर कुछ विसंगतियों के साथ) के गुणों के बारे में भी है। .Net स्रोत-कोड के अंदर इस विषय को छूने वाली कुछ बड़ी टिप्पणियां हैं। लिंक न करने के लिए क्षमा करें, लेकिन अगर मुझे सही से याद है तो इसे खोजना बहुत आसान है (सरणी-वर्ग के अंदर)। (और विसंगतियों पर चर्चा करने वाला एक बड़ा SO प्रश्न भी है .... कहीं ...> __>)
AnorZaken

@ScottRippey सिर्फ FYI करें मुझे यह उत्तर मिला, जो आपकी टिप्पणी के साथ करना है: stackoverflow.com/a/4482567/2063755
डेविड क्लेम्फनर

14

मैंने पाया कि अन्य बेंचमार्क लोगों ने यहाँ कमी की है, इसलिए यहाँ मेरी दरार है। अगर आपको मेरी कार्यप्रणाली में कुछ गड़बड़ लगती है तो मुझे बताएं।

/* This is a benchmarking template I use in LINQPad when I want to do a
 * quick performance test. Just give it a couple of actions to test and
 * it will give you a pretty good idea of how long they take compared
 * to one another. It's not perfect: You can expect a 3% error margin
 * under ideal circumstances. But if you're not going to improve
 * performance by more than 3%, you probably don't care anyway.*/
void Main()
{
    // Enter setup code here
    var values = Enumerable.Range(1, 100000)
        .Select(i => i.ToString())
        .ToArray()
        .Select(i => i);
    values.GetType().Dump();
    var actions = new[]
    {
        new TimedAction("ToList", () =>
        {
            values.ToList();
        }),
        new TimedAction("ToArray", () =>
        {
            values.ToArray();
        }),
        new TimedAction("Control", () =>
        {
            foreach (var element in values)
            {
                // do nothing
            }
        }),
        // Add tests as desired
    };
    const int TimesToRun = 1000; // Tweak this as necessary
    TimeActions(TimesToRun, actions);
}


#region timer helper methods
// Define other methods and classes here
public void TimeActions(int iterations, params TimedAction[] actions)
{
    Stopwatch s = new Stopwatch();
    int length = actions.Length;
    var results = new ActionResult[actions.Length];
    // Perform the actions in their initial order.
    for (int i = 0; i < length; i++)
    {
        var action = actions[i];
        var result = results[i] = new ActionResult { Message = action.Message };
        // Do a dry run to get things ramped up/cached
        result.DryRun1 = s.Time(action.Action, 10);
        result.FullRun1 = s.Time(action.Action, iterations);
    }
    // Perform the actions in reverse order.
    for (int i = length - 1; i >= 0; i--)
    {
        var action = actions[i];
        var result = results[i];
        // Do a dry run to get things ramped up/cached
        result.DryRun2 = s.Time(action.Action, 10);
        result.FullRun2 = s.Time(action.Action, iterations);
    }
    results.Dump();
}

public class ActionResult
{
    public string Message { get; set; }
    public double DryRun1 { get; set; }
    public double DryRun2 { get; set; }
    public double FullRun1 { get; set; }
    public double FullRun2 { get; set; }
}

public class TimedAction
{
    public TimedAction(string message, Action action)
    {
        Message = message;
        Action = action;
    }
    public string Message { get; private set; }
    public Action Action { get; private set; }
}

public static class StopwatchExtensions
{
    public static double Time(this Stopwatch sw, Action action, int iterations)
    {
        sw.Restart();
        for (int i = 0; i < iterations; i++)
        {
            action();
        }
        sw.Stop();

        return sw.Elapsed.TotalMilliseconds;
    }
}
#endregion

आप ऐसा कर सकते हैं यहां LINQPad स्क्रिप्ट डाउनलोड हैं

परिणाम: ToArray बनाम ToList प्रदर्शन

उपरोक्त कोड को घुमाते हुए, आपको पता चलेगा कि:

  1. छोटे सरणियों के साथ काम करते समय अंतर कम महत्वपूर्ण होता हैअधिक पुनरावृत्तियों, लेकिन छोटे सरणियों
  2. इससे निपटने के दौरान अंतर कम महत्वपूर्ण है intएस के बजाय एस केstring
  3. के structबजाय बड़े s का उपयोग करनाstring आम तौर पर बहुत अधिक समय लगता है, लेकिन वास्तव में अनुपात में बहुत बदलाव नहीं होता है।

यह शीर्ष-मतदान उत्तरों के निष्कर्ष से सहमत है:

  1. जब तक आपका कोड अक्सर डेटा की कई बड़ी सूचियों का उत्पादन नहीं करता है, तब तक आपको प्रदर्शन अंतर पर ध्यान देने की संभावना नहीं है। (100K स्ट्रिंग्स एप्स की 1000 सूची बनाते समय केवल 200ms का अंतर था।)
  2. ToList() यदि आप लंबे समय तक परिणामों पर लटकने की योजना नहीं बना रहे हैं, तो लगातार तेजी से चलता है, और एक बेहतर विकल्प होगा।

अपडेट करें

@ जोन्हा ने बताया कि समय के आगे परिणाम के संग्रह के आकार का अनुमान लगाने के लिए या कार्यान्वयन के Selectलिए यह संभव है कि कार्यान्वयन के आधार पर । जगह के साथ उपरोक्त कोड में पैदावार बहुत इसी तरह के परिणाम समय पर और भी बहुत कुछ नेट कार्यान्वयन की तो परवाह किए बिना करने की संभावना है।ToList()ToArray().Select(i => i)Where(i => true)

बेंचमार्क जहाँ का चयन करने के बजाय का उपयोग कर


.NET कोर में दोनों मामले नेटफैक्स की तुलना में यहां बेहतर होने चाहिए, क्योंकि यह महसूस करेगा कि आकार होने जा रहा है 100000और इसका उपयोग करें ToList()और दोनों को अनुकूलित करने के लिए ToArray(), ToArray()बहुत हल्का होने के साथ, क्योंकि इसे हटने की आवश्यकता नहीं है। अन्यथा, जो एक जगह ToList()है फायदा है। प्रश्न में उदाहरण अभी भी खो जाएगा, क्योंकि इस Whereतरह के आकार की भविष्यवाणी नहीं की जा सकती है।
जॉन हन्ना

@ जोहन्ना: त्वरित प्रतिक्रिया के लिए धन्यवाद। मुझे नहीं पता था। .NET Core उस अनुकूलन को बना रहा था। यह अच्छा है। मेरे कोड में, .Select(i => i)उस के .Where(i => true)लिए सही करने के साथ प्रतिस्थापित किया जा सकता है।
स्ट्रिपिंगवर्यर

हाँ, कि यह कोरफैक्स पर अनुकूलन को प्रभावित करेगा। यह दिलचस्प हो सकता है कि दोनों का आकार ऐसा हो जो दो की शक्ति हो (जो ToArray()एक लाभ देनी चाहिए ) और एक जो ऊपर के रूप में नहीं है, और परिणामों की तुलना करें।
जॉन हन्ना

@ जोंहन्ना: दिलचस्प बात यह है कि ToArray() अभी भी सबसे अच्छी स्थिति में हारता है। Math.Pow(2, 15)तत्वों के साथ , यह (ToList: 700ms, ToArray: 900ms) है। एक और तत्व को जोड़ने पर यह (ToList: 925, ToArray: 1350) हो जाता है। मुझे आश्चर्य है कि अगर ToArrayयह पहले से ही सही आकार है तब भी सरणी को कॉपी कर रहा है ? उन्हें शायद लगा कि यह एक दुर्लभ पर्याप्त घटना है कि यह अतिरिक्त सशर्त के लायक नहीं था।
स्ट्रिपिंगवर्यर

यह सटीक आकार के मिलान पर कॉपी नहीं हुआ, इससे पहले ही हमने इसे कोरफैक्स में अनुकूलित करना शुरू कर दिया था, इसलिए यह ऐसा मामला है जहां इसे सबसे अधिक ब्रेक मिलते हैं।
जॉन हन्ना

12

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

यदि प्रदर्शन मायने रखता है, तो आपको यह भी विचार करना चाहिए कि किस पर काम करना तेज होगा। वास्तविक रूप से, आप कॉल ToListया ToArrayमिलियन बार नहीं करेंगे, लेकिन प्राप्त संग्रह पर एक मिलियन बार काम कर सकते हैं। इस संदर्भ में []के बाद से, बेहतर है List<>है []कुछ भूमि के ऊपर के साथ। कुछ दक्षता तुलना के लिए इस धागे को देखें: कौन सा अधिक कुशल है: सूची <int> या int []

कुछ समय पहले अपने स्वयं के परीक्षणों में, मैंने ToArrayतेजी से पाया था । और मुझे यकीन नहीं है कि परीक्षण कैसे तिरछे थे। प्रदर्शन अंतर हालांकि इतना नगण्य है, जो केवल ध्यान देने योग्य है यदि आप इन प्रश्नों को लाखों बार लूप में चला रहे हैं।


2
हां - यदि कंपाइलर जानता है कि आप किसी सरणी (बल्कि IEnumerable <>) की तुलना में पुनरावृति कर रहे हैं, तो यह पुनरावृत्ति को महत्वपूर्ण रूप से अनुकूलित कर सकता है।
रॉबिसक्लोस

12

एक बहुत देर से जवाब लेकिन मुझे लगता है कि यह googlers के लिए उपयोगी होगा।

वे दोनों चूसना जब वे linq का उपयोग कर बनाया। यदि आवश्यक हो तो वे दोनों बफर को आकार देने के लिए समान कोड लागू करते हैं । 4 तत्वों की एक सरणी आवंटित करके, सरणी में ToArrayबदलने के IEnumerable<>लिए आंतरिक रूप से एक वर्ग का उपयोग करता है । यदि यह पर्याप्त नहीं है तो यह एक नया सरणी बनाकर आकार को दोगुना कर देता है और वर्तमान के आकार को दोगुना करके वर्तमान सरणी को कॉपी कर लेता है। अंत में यह आपके आइटमों की गिनती की एक नई सरणी आवंटित करता है। यदि आपकी क्वेरी 129 तत्व वापस आती है, तो ToArray 6 आवंटन और मेमोरी कॉपी ऑपरेशन को 256 तत्व सरणी बनाने के लिए और लौटने के लिए 129 का एक और सरणी बना देगा। स्मृति दक्षता के लिए बहुत कुछ।

ToList एक ही काम करता है, लेकिन यह अंतिम आवंटन को छोड़ देता है क्योंकि आप भविष्य में आइटम जोड़ सकते हैं। सूची परवाह नहीं है अगर यह एक linq क्वेरी से बनाया गया है या मैन्युअल रूप से बनाया गया है।

निर्माण के लिए सूची मेमोरी के साथ बेहतर है, लेकिन सीपीयू के साथ बदतर है क्योंकि सूची एक सामान्य समाधान है हर कार्रवाई के लिए अतिरिक्त चेक की आवश्यकता होती है। सरणियों के लिए नेट की आंतरिक रेंज की जांच।

इसलिए यदि आप कई बार अपने परिणाम सेट के माध्यम से पुनरावृत्ति करेंगे, तो सरणियाँ अच्छी हैं क्योंकि इसका मतलब सूचियों की तुलना में कम रेंज की जांच है, और संकलक आमतौर पर अनुक्रमिक पहुंच के लिए सरणियों का अनुकूलन करते हैं।

यदि आप इसे बनाते समय क्षमता पैरामीटर निर्दिष्ट करते हैं तो सूची का आबंटन आवंटन बेहतर हो सकता है। इस स्थिति में यह आपको केवल एक बार सरणी आवंटित करेगा, यह मानते हुए कि आप परिणाम का आकार जानते हैं। ToListलाइनक इसे प्रदान करने के लिए एक अधिभार निर्दिष्ट नहीं करता है, इसलिए हमें अपना विस्तार विधि बनाना होगा जो दी गई क्षमता के साथ एक सूची बनाता है और फिर उपयोग करता है List<>.AddRange

इस उत्तर को समाप्त करने के लिए मुझे निम्नलिखित वाक्यों को लिखना होगा

  1. अंत में, आप या तो एक ToArray का उपयोग कर सकते हैं, या ToList का, प्रदर्शन इतना अलग नहीं होगा (@ उत्तर) देखें।
  2. आप C # का उपयोग कर रहे हैं। यदि आपको प्रदर्शन की आवश्यकता है, तो उच्च प्रदर्शन कोड के बारे में लिखने के बारे में चिंता न करें, लेकिन खराब प्रदर्शन कोड नहीं लिखने के बारे में चिंता करें।
  3. उच्च प्रदर्शन कोड के लिए हमेशा x64 को लक्षित करें। AFAIK, x64 JIT C ++ कंपाइलर पर आधारित है, और पूंछ पुनरावृत्ति अनुकूलन जैसी कुछ मजेदार चीजें करता है।
  4. 4.5 के साथ आप प्रोफ़ाइल निर्देशित अनुकूलन और मल्टी कोर JIT का आनंद ले सकते हैं।
  5. अंत में, आप इसे जल्दी से संसाधित करने के लिए async / प्रतीक्षा पैटर्न का उपयोग कर सकते हैं।

वे दोनों चूसते हैं? क्या आपके पास एक वैकल्पिक विचार है जिसे अनावश्यक स्मृति आवंटन की आवश्यकता नहीं है?
नवाफल

प्रश्न के संदर्भ में, हाँ, वे दोनों चूसते हैं लेकिन निरर्थक आवंटन के कारण, और कुछ नहीं। निरर्थक आवंटन को कम करने के लिए स्मृति और पुनरावृत्ति गति की कीमत पर लिंक की गई सूचियों का उपयोग किया जा सकता है। दिन के अंत में, यह वही है जो हम करते हैं, हम व्यापार बंद करते हैं। एक और विचार अगर 200 (उदाहरण के लिए) की क्षमता के साथ एक सूची बनाने के लिए और फिर आइटम लोड करें। यह अतिरेक को भी कम करेगा, लेकिन सरणियाँ हमेशा तेज होती हैं, इसलिए यह एक और व्यापार बंद है।
एर्दोगन कुर्तुर

200 की सूची बनाएं ? यह आकार बदलने से बच सकता है , लेकिन मैं इस्तेमाल की जाने वाली अनावश्यक स्मृति के बारे में बात कर रहा था। आप इसकी मदद नहीं कर सकते क्योंकि आकार क्या हो सकता है इसके बारे में कोई पूर्व ज्ञान नहीं है। आप पहले से ही एक के निर्माता में क्षमता निर्दिष्ट कर सकते हैं List<T>, लेकिन जब आप नहीं करते हैं या जब आप नहीं कर सकते, तो आप इसकी मदद नहीं कर सकते।
नवफाल

2
स्मृति में एकमात्र निरर्थक डेटा सरणी की सामग्री है जो पॉइंटर्स (इस मामले में) की एक सूची है। एक मिलियन 64 बिट पॉइंटर्स 8 एमबी मेमोरी के रूप में लेते हैं, जो कि उन मिलियन ऑब्जेक्ट्स की तुलना में कुछ भी नहीं है जो वे इंगित करते हैं। 200 केवल एक संख्या है, और इसमें अधिकतम 5 बार कॉल को आकार बदलने की संख्या को कम करने का मौका है। और हां, हम इसकी मदद नहीं कर सकते। हमारे पास बेहतर विकल्प नहीं हैं। मेरे पास बेहतर समाधान नहीं है, लेकिन इसका मतलब यह नहीं है कि मुझे यह कहने की अनुमति नहीं है कि समस्या कहां है।
एर्दोगन कुर्तुर

1
हम्म अंत में यह वह जगह है जहां आप रेखा खींचते हैं। मुझे वर्तमान कार्यान्वयन पसंद है। आपके उत्तर के लहजे ने मुझे यह
समझा

7

यह एक पुराना सवाल है - लेकिन उन उपयोगकर्ताओं के लाभ के लिए जो इस पर ठोकर खाते हैं, वहाँ भी है और 'मेमोइज़िंग' द एनम्यूएरेबल का विकल्प भी है - जिसमें लाइनक स्टेटमेंट के कई एन्यूमरेशन को रोकने और रोकने का प्रभाव होता है, जो है और ToList () का उपयोग बहुत किया जाता है, भले ही सूची या सरणी का संग्रह गुण कभी भी उपयोग नहीं किया जाता है।

ज्ञापन RX / System.Interactive lib में उपलब्ध है, और यहाँ समझाया गया है: System.Interactive के साथ अधिक LINQ

( बार्ट डी'मैट के ब्लॉग से जो अत्यधिक अनुशंसित पढ़ा जाता है यदि आप लिनक के साथ वस्तुओं पर बहुत काम कर रहे हैं)


4

एक विकल्प अपने खुद के विस्तार विधि है कि एक रिटर्न जोड़ना है केवल पढ़ने के लिए ICollection<T> । यह उपयोग करने से बेहतर हो सकता है ToListया ToArrayजब आप किसी सरणी / सूची के अनुक्रमण गुणों का उपयोग नहीं करना चाहते हैं या सूची से जोड़ना / हटाना चाहते हैं।

public static class EnumerableExtension
{
    /// <summary>
    /// Causes immediate evaluation of the linq but only if required.
    /// As it returns a readonly ICollection, is better than using ToList or ToArray
    /// when you do not want to use the indexing properties of an IList, or add to the collection.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="enumerable"></param>
    /// <returns>Readonly collection</returns>
    public static ICollection<T> Evaluate<T>(this IEnumerable<T> enumerable)
    {
        //if it's already a readonly collection, use it
        var collection = enumerable as ICollection<T>;
        if ((collection != null) && collection.IsReadOnly)
        {
            return collection;
        }
        //or make a new collection
        return enumerable.ToList().AsReadOnly();
    }
}

इकाई परीक्षण:

[TestClass]
public sealed class EvaluateLinqTests
{
    [TestMethod]
    public void EvalTest()
    {
        var list = new List<int> {1, 2, 3};
        var linqResult = list.Select(i => i);
        var linqResultEvaluated = list.Select(i => i).Evaluate();
        list.Clear();
        Assert.AreEqual(0, linqResult.Count());
        //even though we have cleared the underlying list, the evaluated list does not change
        Assert.AreEqual(3, linqResultEvaluated.Count());
    }

    [TestMethod]
    public void DoesNotSaveCreatingListWhenHasListTest()
    {
        var list = new List<int> {1, 2, 3};
        var linqResultEvaluated = list.Evaluate();
        //list is not readonly, so we expect a new list
        Assert.AreNotSame(list, linqResultEvaluated);
    }

    [TestMethod]
    public void SavesCreatingListWhenHasReadonlyListTest()
    {
        var list = new List<int> {1, 2, 3}.AsReadOnly();
        var linqResultEvaluated = list.Evaluate();
        //list is readonly, so we don't expect a new list
        Assert.AreSame(list, linqResultEvaluated);
    }

    [TestMethod]
    public void SavesCreatingListWhenHasArrayTest()
    {
        var list = new[] {1, 2, 3};
        var linqResultEvaluated = list.Evaluate();
        //arrays are readonly (wrt ICollection<T> interface), so we don't expect a new object
        Assert.AreSame(list, linqResultEvaluated);
    }

    [TestMethod]
    [ExpectedException(typeof (NotSupportedException))]
    public void CantAddToResultTest()
    {
        var list = new List<int> {1, 2, 3};
        var linqResultEvaluated = list.Evaluate();
        Assert.AreNotSame(list, linqResultEvaluated);
        linqResultEvaluated.Add(4);
    }

    [TestMethod]
    [ExpectedException(typeof (NotSupportedException))]
    public void CantRemoveFromResultTest()
    {
        var list = new List<int> {1, 2, 3};
        var linqResultEvaluated = list.Evaluate();
        Assert.AreNotSame(list, linqResultEvaluated);
        linqResultEvaluated.Remove(1);
    }
}

यह ध्यान देने योग्य है कि रीड-ओनली कलेक्शन कॉन्ट्रैक्ट केवल यह निर्धारित करता है कि ऑब्जेक्ट का उपयोगकर्ता इसे संशोधित नहीं कर सकता है, लेकिन मालिक अभी भी ऐसा कर सकता है यदि वह इसका संदर्भ रखता है जो एक म्यूट इंटरफ़ेस प्रस्तुत करता है। उन इंटरफेस के लिए जो गारंटी देते हैं कि अंतर्निहित संरचना कभी नहीं बदलेगी, अपरिवर्तनीय संग्रह को देखें। क्यों अपरिवर्तनीय, या केवल पढ़ने के लिए, या सादे पढ़ने-लिखने के संग्रह बेहतर या बदतर हैं, किसी को तुलना के लिए संदर्भ बिंदु की आवश्यकता है; कोई अंतिम उत्तर नहीं है (अन्यथा हमें नहीं चुनना होगा)।
tne

@ ध्यान दें, मैं AsReadOnly से पहले टॉलिस्ट करता हूं, इसलिए अंतर्निहित म्यूटेबल का कोई संदर्भ नहीं है।
पश्चिमोत्तर

आप पूरी तरह से सही हैं, और संभवतः बीसीएल में संग्रहणीय संग्रह आने से पहले चीजों को करने का सबसे अच्छा तरीका है (मुझे लगता है कि आपके जवाब के एक महीने बाद पहला बीटा सामने आया)।
tne

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

4

ToListAsync<T>() पसंद है।

एंटिटी फ्रेमवर्क 6 में दोनों विधियां अंततः एक ही आंतरिक विधि को ToArrayAsync<T>()कहते हैं , लेकिन list.ToArray()अंत में कॉल करते हैं, जिसे इस रूप में लागू किया जाता है

T[] array = new T[_size];
Array.Copy(_items, 0, array, 0, _size);
return array;

तो ToArrayAsync<T>()कुछ ओवरहेड्स है, इस तरह ToListAsync<T>()पसंद किया जाता है।


1
यह वास्तव में वह उत्तर है जिसकी मुझे तलाश थी, ईएफ कैसे करता है। मैं उत्सुक हूँ कि यह EF कोर के बारे में कैसे है।
शिम्मी वेइटहैंडलर

3

पुराने प्रश्न लेकिन हर समय नए प्रश्नकर्ता।

System.Linq.Enumerable के स्रोत के अनुसार , ToListबस a को वापस लौटाएं new List(source), जबकि ToArraya new Buffer<T>(source).ToArray()को वापस करने के लिए a का उपयोग करें T[]

स्मृति आवंटन के बारे में:

किसी IEnumerable<T>एकमात्र ऑब्जेक्ट पर चलते समय , ToArrayमेमोरी को एक से अधिक बार आवंटित करें ToList। लेकिन आपको ज्यादातर मामलों में इसके बारे में परवाह करने की ज़रूरत नहीं है, क्योंकि जीसी कचरा संग्रह तब करेगा जब जरूरत होगी।

रनटाइम कुशल के बारे में:

जो लोग इस सवाल पर सवाल उठा रहे हैं वे निम्नलिखित कोड को अपनी मशीन पर चला सकते हैं, और आपको अपना जवाब मिल जाएगा।

class PersonC
{
    public Guid uuid;
    public string name;
    public int age;
    public bool sex;
    public DateTime BirthDay;
    public double weight;
}

struct PersonS
{
    public Guid uuid;
    public string name;
    public int age;
    public bool sex;
    public DateTime BirthDay;
    public double weight;
}

class PersonT<T> : IEnumerable<T>
{
    private List<T> items;
    public PersonT(IEnumerable<T> init)
    {
        items = new List<T>(init);
    }

    public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator();
}

private IEnumerable<PersonC> C(int count)
{
    for (var i = 0; i < count; ++i)
    {
        var guid = Guid.NewGuid();
        var guidBytes = guid.ToByteArray(); //16 bytes
        yield return new PersonC
        {
            uuid = guid,
            name = guid.ToString(),
            age = guidBytes[0] ^ guidBytes[7],
            sex = guidBytes[14] % 2 == 0,
            BirthDay = DateTime.Now.AddDays(-guidBytes[11] * 18),
            weight = guidBytes[12] * 100
        };
    }
}

private IEnumerable<PersonS> S(int count)
{
    for (var i = 0; i < count; ++i)
    {
        var guid = Guid.NewGuid();
        var guidBytes = guid.ToByteArray(); //16 bytes
        yield return new PersonS
        {
            uuid = guid,
            name = guid.ToString(),
            age = guidBytes[0] ^ guidBytes[7],
            sex = guidBytes[14] % 2 == 0,
            BirthDay = DateTime.Now.AddDays(-guidBytes[11] * 18),
            weight = guidBytes[12] * 100
        };
    }
}

private void MakeLog(string test, List<long> log) =>
    Console.WriteLine("{0} {1} ms -> [{2}]",
        test,
        log.Average(),
        string.Join(", ", log)
    );

private void Test1(int times, int count)
{
    var test = Enumerable.Range(1, times).ToArray();

    MakeLog("C.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = C(count).ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("C.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = C(count).ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = S(count).ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = S(count).ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());
}

private void Test2(int times, int count)
{
    var test = Enumerable.Range(1, times).ToArray();

    var dataC1 = new PersonT<PersonC>(C(count));
    var dataS1 = new PersonT<PersonS>(S(count));

    MakeLog("C1.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataC1.ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("C1.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataC1.ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S1.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataS1.ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S1.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataS1.ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());
}

private void Test3(int times, int count)
{
    var test = Enumerable.Range(1, times).ToArray();

    var dataC2 = (ICollection<PersonC>) new List<PersonC>(C(count));
    var dataS2 = (ICollection<PersonS>) new List<PersonS>(S(count));

    MakeLog("C2.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataC2.ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("C2.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataC2.ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S2.ToList", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataS2.ToList();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());

    MakeLog("S2.ToArray", test.Select(o =>
    {
        var sw = new Stopwatch();
        GC.Collect();
        sw.Start();
        var ret = dataS2.ToArray();
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }).ToList());
}

private void TestMain()
{
    const int times = 100;
    const int count = 1_000_000 + 1;
    Test1(times, count);
    Test2(times, count);
    Test3(times, count);
}

मुझे अपनी मशीन पर ये परिणाम मिले:

समूह 1:

C.ToList 761.79 ms -> [775, 755, 759, 759, 756, 759, 765, 750, 757, 762, 759, 754, 757, 753, 763, 753, 759, 756, 768, 754, 763, 757, 757, 777, 780, 758, 754, 758, 762, 754, 758, 757, 763, 758, 760, 754, 761, 755, 764, 847, 952, 755, 747, 763, 760, 758, 754, 763, 761, 758, 750, 764, 757, 763, 762, 756, 753, 759, 759, 757, 758, 779, 765, 760, 760, 756, 760, 756, 755, 764, 759, 753, 757, 760, 752, 764, 758, 760, 758, 760, 755, 761, 751, 753, 761, 762, 761, 758, 759, 752, 765, 756, 760, 755, 757, 753, 760, 751, 755, 779]
C.ToArray 782.56 ms -> [783, 774, 771, 771, 773, 774, 775, 775, 772, 770, 771, 774, 771, 1023, 975, 772, 767, 776, 771, 779, 772, 779, 775, 771, 775, 773, 775, 771, 765, 774, 770, 781, 772, 771, 781, 762, 817, 770, 775, 779, 769, 774, 763, 775, 777, 769, 777, 772, 775, 778, 775, 771, 770, 774, 772, 769, 772, 769, 774, 775, 768, 775, 769, 774, 771, 776, 774, 773, 778, 769, 778, 767, 770, 787, 783, 779, 771, 768, 805, 780, 779, 767, 773, 771, 773, 785, 1044, 853, 775, 774, 775, 771, 770, 769, 770, 776, 770, 780, 821, 770]
S.ToList 704.2 ms -> [687, 702, 709, 691, 694, 710, 696, 698, 700, 694, 701, 719, 706, 694, 702, 699, 699, 703, 704, 701, 703, 705, 697, 707, 691, 697, 707, 692, 721, 698, 695, 700, 704, 700, 701, 710, 700, 705, 697, 711, 694, 700, 695, 698, 701, 692, 696, 702, 690, 699, 708, 700, 703, 714, 701, 697, 700, 699, 694, 701, 697, 696, 699, 694, 709, 1068, 690, 706, 699, 699, 695, 708, 695, 704, 704, 700, 695, 704, 695, 696, 702, 700, 710, 708, 693, 697, 702, 694, 700, 706, 699, 695, 706, 714, 704, 700, 695, 697, 707, 704]
S.ToArray 742.5 ms -> [742, 743, 733, 745, 741, 724, 738, 745, 728, 732, 740, 727, 739, 740, 726, 744, 758, 732, 744, 745, 730, 739, 738, 723, 745, 757, 729, 741, 736, 724, 744, 756, 739, 766, 737, 725, 741, 742, 736, 748, 742, 721, 746, 1043, 806, 747, 731, 727, 742, 742, 726, 738, 746, 727, 739, 743, 730, 744, 753, 741, 739, 746, 728, 740, 744, 734, 734, 738, 731, 747, 736, 731, 765, 735, 726, 740, 743, 730, 746, 742, 725, 731, 757, 734, 738, 741, 732, 747, 744, 721, 742, 741, 727, 745, 740, 730, 747, 760, 737, 740]

C1.ToList 32.34 ms -> [35, 31, 31, 31, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 33, 32, 31, 31, 31, 31, 30, 32, 31, 31, 31, 31, 32, 30, 31, 31, 31, 30, 32, 31, 31, 31, 36, 31, 31, 31, 32, 30, 31, 32, 31, 31, 31, 31, 31, 32, 31, 31, 31, 31, 33, 32, 31, 32, 31, 31, 33, 31, 31, 31, 31, 31, 32, 31, 32, 31, 34, 38, 68, 42, 79, 33, 31, 31, 31, 31, 31, 30, 30, 30, 30, 31, 31, 31, 31, 32, 31, 32, 31, 31, 31, 32, 33, 33, 31, 31]
C1.ToArray 56.32 ms -> [57, 56, 59, 54, 54, 55, 56, 57, 54, 54, 55, 55, 57, 56, 59, 57, 56, 58, 56, 56, 54, 56, 57, 55, 55, 55, 57, 58, 57, 58, 55, 55, 56, 55, 57, 56, 56, 59, 56, 56, 56, 56, 58, 56, 57, 56, 56, 57, 56, 55, 56, 56, 56, 59, 56, 56, 56, 55, 55, 54, 55, 54, 57, 56, 56, 56, 55, 55, 56, 56, 56, 59, 56, 56, 57, 56, 57, 56, 56, 56, 56, 62, 55, 56, 56, 56, 69, 57, 58, 56, 57, 58, 56, 57, 56, 56, 56, 56, 56, 56]
S1.ToList 88.69 ms -> [96, 90, 90, 89, 91, 88, 89, 90, 96, 89, 89, 89, 90, 90, 90, 89, 90, 90, 89, 90, 89, 91, 89, 91, 89, 91, 89, 90, 90, 89, 87, 88, 87, 88, 87, 87, 87, 87, 88, 88, 87, 87, 89, 87, 87, 87, 91, 88, 87, 86, 89, 87, 90, 89, 89, 90, 89, 87, 87, 87, 86, 87, 88, 90, 88, 87, 87, 92, 87, 87, 88, 88, 88, 86, 86, 87, 88, 87, 87, 87, 89, 87, 89, 87, 90, 89, 89, 89, 91, 89, 90, 89, 90, 88, 90, 90, 90, 88, 89, 89]
S1.ToArray 143.26 ms -> [130, 129, 130, 131, 133, 130, 131, 130, 135, 137, 130, 136, 132, 131, 130, 131, 132, 130, 132, 136, 130, 131, 157, 153, 194, 364, 176, 189, 203, 194, 189, 192, 183, 140, 142, 147, 145, 134, 159, 158, 142, 167, 130, 143, 145, 144, 160, 154, 156, 153, 153, 164, 142, 145, 137, 134, 145, 143, 142, 135, 133, 133, 135, 134, 134, 139, 139, 133, 134, 141, 133, 132, 133, 132, 133, 131, 135, 132, 133, 132, 128, 128, 130, 132, 129, 129, 129, 129, 129, 128, 134, 129, 129, 129, 129, 128, 128, 137, 130, 131]

C2.ToList 3.25 ms -> [5, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3]
C2.ToArray 3.37 ms -> [4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 4, 9, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 4, 4, 3, 4, 4, 3, 3, 4, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 4, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3]
S2.ToList 37.72 ms -> [38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 40, 38, 38, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 39, 37, 37, 39, 38, 37, 37, 37, 37, 39, 38, 37, 37, 38, 37, 38, 37, 37, 38, 37, 37, 37, 38, 37, 37, 36, 37, 38, 37, 39, 37, 39, 38, 37, 38, 38, 38, 38, 38, 38, 37, 38, 38, 38, 38, 38, 37, 38, 37, 37, 38, 37, 37, 39, 41, 37, 38, 38, 37, 37, 37, 37, 38, 37, 37, 37, 40, 37, 37, 37, 37, 39, 38]
S2.ToArray 38.86 ms -> [39, 37, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 38, 38, 38, 39, 37, 38, 38, 38, 38, 38, 37, 37, 38, 37, 37, 38, 38, 40, 38, 38, 38, 38, 38, 39, 38, 38, 39, 38, 38, 39, 38, 38, 40, 38, 39, 38, 38, 39, 38, 38, 38, 38, 38, 39, 38, 38, 38, 39, 39, 37, 38, 38, 39, 71, 78, 37, 37, 37, 39, 38, 38, 39, 38, 38, 38, 38, 38, 39, 38, 38, 38, 39, 38, 38, 38]

समूह 2:

C.ToList 756.81 ms
C.ToArray 774.21 ms
S.ToList 709.7 ms
S.ToArray 753.51 ms

C1.ToList 32.06 ms
C1.ToArray 56.58 ms
S1.ToList 89.43 ms
S1.ToArray 132.85 ms

C2.ToList 3.45 ms
C2.ToArray 3.36 ms
S2.ToList 41.43 ms
S2.ToArray 40.84 ms

Group3:

C.ToList 756.64 ms
C.ToArray 771.56 ms
S.ToList 705.42 ms
S.ToArray 749.59 ms

C1.ToList 31.45 ms
C1.ToArray 57.03 ms
S1.ToList 91.26 ms
S1.ToArray 129.77 ms

C2.ToList 3.26 ms
C2.ToArray 3.29 ms
S2.ToList 41.57 ms
S2.ToArray 40.69 ms

GROUP4:

C.ToList 729.65 ms -> [749, 730, 721, 719, 723, 743, 721, 724, 727, 722, 716, 725, 723, 726, 718, 722, 731, 722, 723, 725, 723, 722, 728, 726, 728, 718, 726, 1088, 788, 737, 729, 710, 730, 728, 717, 723, 728, 721, 722, 728, 722, 736, 723, 729, 732, 724, 726, 727, 728, 728, 726, 726, 725, 727, 725, 728, 728, 718, 724, 725, 726, 724, 726, 729, 727, 722, 722, 725, 725, 728, 724, 727, 738, 717, 726, 723, 725, 725, 727, 724, 720, 726, 726, 723, 727, 730, 723, 721, 725, 727, 727, 733, 720, 722, 722, 725, 722, 725, 728, 726]
C.ToArray 788.36 ms -> [748, 740, 742, 797, 1090, 774, 781, 787, 784, 786, 786, 782, 781, 781, 784, 783, 783, 781, 783, 787, 783, 784, 775, 789, 784, 785, 778, 774, 781, 783, 786, 781, 780, 788, 778, 785, 777, 781, 786, 782, 781, 787, 782, 787, 784, 773, 783, 782, 781, 777, 783, 781, 785, 788, 777, 776, 784, 784, 783, 789, 778, 781, 791, 768, 779, 783, 781, 787, 786, 781, 784, 781, 785, 781, 780, 809, 1155, 780, 790, 789, 783, 776, 785, 783, 786, 787, 782, 782, 787, 777, 779, 784, 783, 776, 786, 775, 782, 779, 784, 784]
S.ToList 705.54 ms -> [690, 705, 709, 708, 702, 707, 703, 696, 703, 702, 700, 703, 700, 707, 705, 699, 697, 703, 695, 698, 707, 697, 711, 710, 699, 700, 708, 707, 693, 710, 704, 691, 702, 700, 703, 700, 705, 700, 703, 695, 709, 705, 698, 699, 709, 700, 699, 704, 691, 705, 703, 700, 708, 1048, 710, 706, 706, 692, 702, 705, 695, 701, 710, 697, 698, 706, 705, 707, 707, 695, 698, 704, 698, 699, 705, 698, 703, 702, 701, 697, 702, 702, 704, 703, 699, 707, 703, 705, 701, 717, 698, 695, 713, 696, 708, 705, 697, 699, 700, 698]
S.ToArray 745.01 ms -> [751, 743, 727, 734, 736, 745, 739, 750, 739, 750, 758, 739, 744, 738, 730, 744, 745, 739, 744, 750, 733, 735, 743, 731, 749, 748, 727, 746, 749, 731, 737, 803, 1059, 756, 769, 748, 740, 745, 741, 746, 749, 732, 741, 742, 732, 744, 746, 737, 742, 739, 733, 744, 741, 729, 746, 760, 725, 741, 764, 739, 750, 751, 727, 745, 738, 727, 735, 741, 720, 736, 740, 733, 741, 746, 731, 749, 756, 740, 738, 736, 732, 741, 741, 733, 741, 744, 736, 742, 742, 735, 743, 746, 729, 748, 765, 743, 734, 742, 728, 749]

C1.ToList 32.27 ms -> [36, 31, 31, 32, 31, 32, 31, 30, 32, 30, 30, 30, 34, 32, 31, 31, 31, 31, 31, 31, 31, 32, 38, 51, 68, 57, 35, 30, 31, 31, 30, 30, 33, 30, 31, 34, 31, 34, 32, 31, 31, 31, 31, 32, 30, 30, 31, 30, 31, 31, 32, 31, 31, 31, 32, 31, 31, 31, 32, 31, 33, 31, 31, 32, 30, 30, 30, 30, 30, 33, 30, 33, 32, 31, 30, 31, 31, 32, 32, 31, 35, 31, 34, 31, 31, 32, 31, 31, 32, 31, 32, 31, 31, 35, 31, 31, 31, 31, 31, 32]
C1.ToArray 56.72 ms -> [58, 56, 57, 57, 59, 58, 58, 57, 56, 59, 57, 55, 55, 54, 56, 55, 56, 56, 57, 59, 56, 55, 58, 56, 55, 55, 55, 55, 58, 58, 55, 57, 57, 56, 57, 57, 57, 57, 59, 59, 56, 57, 56, 57, 57, 56, 57, 59, 58, 56, 57, 57, 57, 58, 56, 56, 59, 56, 59, 57, 57, 57, 57, 59, 57, 56, 57, 56, 58, 56, 57, 56, 57, 59, 55, 58, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 56, 56, 57, 56, 56, 57, 58, 57, 57, 57, 57, 57]
S1.ToList 90.72 ms -> [95, 90, 90, 89, 89, 89, 91, 89, 89, 87, 91, 89, 89, 89, 91, 89, 89, 89, 90, 89, 89, 90, 88, 89, 88, 90, 89, 90, 89, 89, 90, 90, 89, 89, 90, 91, 89, 91, 89, 90, 89, 89, 90, 91, 89, 89, 89, 89, 89, 89, 90, 89, 89, 89, 90, 89, 90, 89, 91, 89, 90, 89, 90, 89, 90, 89, 96, 89, 90, 89, 89, 89, 89, 89, 90, 89, 89, 89, 90, 87, 89, 90, 90, 91, 89, 91, 89, 89, 90, 91, 90, 89, 93, 144, 149, 90, 90, 89, 89, 89]
S1.ToArray 131.4 ms -> [130, 128, 127, 134, 129, 129, 130, 136, 131, 130, 132, 132, 133, 131, 132, 131, 133, 132, 130, 131, 132, 131, 130, 133, 133, 130, 130, 131, 131, 131, 132, 134, 131, 131, 132, 131, 132, 131, 134, 131, 131, 130, 131, 131, 130, 132, 129, 131, 131, 131, 132, 131, 133, 134, 131, 131, 132, 132, 131, 133, 131, 131, 130, 133, 131, 130, 134, 132, 131, 132, 132, 131, 131, 134, 131, 131, 132, 132, 131, 130, 138, 130, 130, 131, 132, 132, 130, 134, 131, 131, 132, 131, 130, 132, 133, 131, 131, 131, 130, 131]

C2.ToList 3.21 ms -> [4, 3, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3]
C2.ToArray 3.22 ms -> [4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 4]
S2.ToList 41.46 ms -> [42, 40, 41, 40, 42, 40, 40, 40, 40, 40, 40, 40, 40, 41, 40, 40, 41, 40, 40, 40, 39, 41, 41, 39, 40, 40, 43, 40, 39, 40, 40, 40, 40, 40, 40, 41, 40, 40, 40, 43, 40, 43, 75, 76, 47, 39, 40, 40, 40, 40, 42, 40, 41, 40, 40, 40, 44, 41, 40, 42, 42, 40, 41, 41, 41, 41, 41, 40, 41, 41, 41, 41, 42, 41, 40, 41, 41, 42, 42, 41, 40, 41, 41, 41, 41, 41, 40, 42, 40, 42, 41, 41, 41, 43, 41, 41, 41, 41, 42, 41]
S2.ToArray 41.14 ms -> [42, 41, 41, 40, 40, 40, 40, 41, 41, 42, 41, 42, 41, 41, 41, 42, 41, 41, 42, 41, 41, 41, 41, 41, 42, 40, 41, 40, 42, 40, 42, 41, 40, 42, 41, 41, 43, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 41, 41, 41, 40, 42, 41, 41, 41, 41, 41, 40, 41, 41, 42, 41, 41, 41, 42, 41, 41, 41, 41, 41, 41, 42, 42, 42, 41, 45, 46, 41, 40, 41, 41, 42, 41, 41, 41, 41, 41, 41, 40, 41, 43, 40, 40, 40, 40, 43, 41]

Group5:

C.ToList 757.06 ms -> [770, 752, 752, 751, 778, 763, 761, 763, 747, 758, 748, 747, 754, 749, 752, 753, 756, 762, 750, 753, 756, 749, 755, 757, 755, 756, 755, 744, 753, 758, 747, 751, 759, 751, 761, 755, 746, 752, 752, 749, 746, 752, 753, 755, 752, 755, 754, 754, 966, 937, 749, 759, 748, 747, 754, 749, 755, 750, 746, 754, 757, 752, 753, 745, 758, 755, 761, 753, 751, 755, 755, 752, 746, 756, 755, 746, 742, 751, 751, 749, 752, 751, 756, 756, 755, 742, 749, 754, 749, 756, 753, 751, 754, 752, 751, 754, 753, 749, 755, 756]
C.ToArray 772.8 ms -> [766, 772, 755, 763, 758, 767, 763, 762, 761, 768, 769, 763, 770, 757, 765, 760, 766, 759, 764, 761, 760, 777, 1102, 881, 759, 765, 758, 762, 772, 761, 758, 757, 765, 769, 769, 761, 762, 762, 763, 760, 770, 764, 760, 768, 758, 766, 763, 770, 769, 761, 764, 761, 761, 767, 761, 762, 764, 757, 765, 766, 767, 771, 753, 762, 769, 768, 759, 764, 764, 760, 763, 763, 763, 763, 763, 767, 761, 771, 760, 765, 760, 758, 768, 770, 751, 771, 767, 771, 765, 763, 760, 765, 765, 769, 767, 767, 1193, 774, 767, 764]
S.ToList 704.73 ms -> [682, 708, 705, 699, 705, 704, 695, 703, 702, 699, 701, 708, 699, 702, 703, 701, 701, 699, 701, 707, 707, 700, 701, 705, 700, 697, 706, 702, 701, 706, 699, 692, 702, 697, 707, 704, 697, 698, 699, 699, 702, 703, 698, 697, 702, 703, 702, 704, 694, 697, 707, 695, 711, 710, 700, 693, 703, 699, 699, 706, 698, 701, 703, 704, 698, 706, 700, 704, 701, 699, 702, 705, 694, 698, 709, 736, 1053, 704, 694, 700, 698, 696, 701, 700, 700, 706, 706, 692, 698, 707, 703, 695, 703, 699, 694, 708, 695, 694, 706, 695]
S.ToArray 744.17 ms -> [746, 740, 725, 740, 739, 731, 746, 760, 735, 738, 740, 734, 744, 748, 737, 744, 745, 727, 736, 738, 728, 743, 745, 735, 748, 760, 739, 748, 762, 742, 741, 747, 733, 746, 758, 742, 742, 741, 724, 744, 747, 727, 740, 740, 729, 742, 757, 741, 740, 742, 726, 739, 746, 1133, 749, 737, 730, 740, 747, 733, 747, 752, 731, 747, 742, 730, 741, 749, 731, 749, 743, 730, 747, 742, 731, 737, 745, 734, 739, 735, 727, 743, 752, 731, 744, 742, 729, 740, 746, 731, 739, 746, 733, 745, 743, 733, 739, 742, 727, 737]

C1.ToList 31.71 ms -> [35, 32, 32, 30, 31, 33, 31, 32, 32, 31, 31, 32, 32, 33, 32, 31, 31, 32, 31, 32, 32, 32, 31, 32, 33, 32, 31, 31, 31, 32, 31, 34, 31, 31, 32, 33, 32, 32, 31, 32, 34, 32, 31, 32, 33, 31, 32, 32, 31, 32, 32, 32, 32, 32, 32, 31, 31, 32, 31, 33, 30, 31, 32, 30, 30, 33, 32, 32, 34, 31, 31, 31, 31, 32, 31, 31, 31, 31, 32, 31, 31, 33, 31, 32, 32, 32, 33, 32, 31, 31, 31, 31, 31, 32, 32, 33, 32, 31, 31, 32]
C1.ToArray 59.53 ms -> [63, 57, 58, 58, 57, 59, 59, 57, 60, 131, 127, 67, 58, 56, 59, 56, 57, 58, 58, 58, 57, 59, 60, 57, 57, 59, 60, 57, 57, 57, 58, 58, 58, 58, 57, 57, 61, 57, 58, 57, 57, 57, 57, 57, 58, 58, 58, 58, 57, 58, 59, 57, 58, 57, 57, 59, 58, 58, 59, 57, 59, 57, 56, 56, 59, 56, 56, 59, 57, 58, 58, 58, 57, 58, 59, 59, 58, 57, 58, 62, 65, 57, 57, 57, 58, 60, 59, 58, 59, 57, 58, 57, 58, 59, 58, 58, 58, 59, 60, 58]
S1.ToList 82.78 ms -> [87, 82, 83, 83, 82, 82, 83, 84, 82, 83, 84, 84, 84, 82, 82, 84, 82, 84, 83, 84, 82, 82, 82, 81, 83, 83, 83, 84, 84, 82, 82, 83, 83, 83, 82, 83, 85, 83, 82, 82, 84, 82, 82, 83, 83, 83, 82, 82, 82, 83, 82, 83, 82, 84, 82, 83, 82, 83, 82, 82, 82, 84, 82, 83, 82, 82, 86, 83, 83, 82, 83, 83, 83, 82, 84, 82, 83, 81, 82, 82, 82, 82, 83, 83, 83, 82, 83, 84, 83, 82, 83, 83, 83, 82, 83, 84, 82, 82, 83, 83]
S1.ToArray 122.3 ms -> [122, 119, 119, 120, 119, 120, 120, 121, 119, 119, 122, 120, 120, 120, 122, 120, 123, 120, 120, 120, 121, 123, 120, 120, 120, 121, 120, 121, 122, 120, 123, 119, 121, 118, 121, 120, 120, 120, 119, 124, 119, 121, 119, 120, 120, 120, 120, 120, 122, 121, 123, 230, 203, 123, 119, 119, 122, 119, 120, 120, 120, 122, 120, 121, 120, 121, 120, 121, 120, 121, 120, 120, 120, 121, 122, 121, 123, 119, 119, 119, 119, 121, 120, 120, 120, 122, 121, 122, 119, 120, 120, 121, 121, 120, 121, 120, 121, 118, 118, 118]

C2.ToList 3.43 ms -> [5, 3, 4, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 4, 3, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 6, 4, 4, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 4, 4, 3, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3]
C2.ToArray 3.48 ms -> [3, 3, 3, 3, 4, 4, 3, 4, 4, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 4, 3, 3, 4, 3, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 3, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 3]
S2.ToList 41.47 ms -> [41, 41, 49, 67, 82, 41, 41, 40, 40, 40, 40, 40, 41, 40, 40, 40, 40, 40, 41, 40, 42, 42, 40, 40, 41, 41, 41, 40, 41, 40, 41, 40, 41, 40, 42, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 42, 41, 41, 41, 42, 40, 41, 40, 40, 40, 42, 40, 41, 42, 41, 42, 41, 42, 40, 41, 41, 41, 41, 41, 41, 41, 41, 40, 41, 40, 41, 41, 41, 40, 41, 41, 40, 40, 41, 41, 41, 41, 41, 43, 40, 40, 41, 42, 41]
S2.ToArray 40.62 ms -> [42, 41, 44, 40, 40, 40, 40, 41, 41, 40, 41, 41, 41, 40, 41, 41, 40, 41, 41, 40, 41, 40, 40, 41, 42, 41, 41, 41, 40, 40, 40, 40, 40, 41, 41, 42, 40, 41, 41, 41, 41, 41, 40, 42, 40, 40, 41, 41, 41, 40, 41, 40, 40, 40, 40, 40, 41, 40, 40, 41, 40, 40, 40, 40, 41, 40, 41, 41, 41, 40, 41, 41, 40, 41, 40, 41, 42, 40, 41, 41, 42, 41, 41, 40, 41, 40, 41, 40, 41, 41, 40, 40, 40, 41, 41, 40, 40, 40, 40, 40]

उत्तर की वर्ण राशि के लिए स्टैक्वेरफ़्लो की सीमा के कारण, Group2 और Group3 की नमूना सूची छोड़ दी जाती है।

जैसा कि आप देख सकते हैं, यह वास्तव में उपयोग करने के लिए ToListया ToArryज्यादातर मामलों में महत्वपूर्ण नहीं है ।

क्रम-गणना को संसाधित करते समय IEnumerable<T>वस्तुओं, अगर लोड गणना द्वारा लाया स्मृति आवंटन की तुलना में भारी है और के संचालन कॉपी ToListऔर ToArray, असमानता तुच्छ (है C.ToList vs C.ToArrayऔर S.ToList vs S.ToArray)।

अंतर केवल गैर-रनटाइम परिकलित IEnumerable<T>ऑब्जेक्ट्स ( C1.ToList vs C1.ToArrayऔर S1.ToList vs S1.ToArray) पर ही देखा जा सकता है । लेकिन एक लाख छोटी वस्तु पर पूर्ण अंतर (<60ms) अभी भी स्वीकार्य है IEnumerable<T>। वास्तव में, अंतर के कार्यान्वयन से तय होता Enumerator<T>है IEnumerable<T>। इसलिए, यदि आपका कार्यक्रम वास्तव में इस पर वास्तव में संवेदनशील है, तो आपको प्रोफ़ाइल, प्रोफ़ाइल, प्रोफ़ाइल करना होगा ! अंत में आप शायद पाएंगे कि टोंटी पर ToListया नहीं है ToArray, लेकिन enumerators का विस्तार।

और, परिणाम C2.ToList vs C2.ToArrayऔर S2.ToList vs S2.ToArrayशो, आप सच में ध्यान की जरूरत नहीं है ToListया ToArrayगैर-क्रम-गणना पर ICollection<T>वस्तुओं।

बेशक, यह सिर्फ मेरी मशीन पर परिणाम है, अलग-अलग मशीन पर इन कार्यों का वास्तविक समय खर्च समान नहीं होगा, आप ऊपर कोड का उपयोग करके अपनी मशीन पर पता लगा सकते हैं।

केवल एक विकल्प आपको पसंद करने की आवश्यकता है, आपको @Jeppe Stig Nielsen के उत्तर के अनुसार, विशिष्ट आवश्यकताओं की आवश्यकता है List<T>या ।T[]


1

इस तरह के रूप में एक और Linq-to-sql में इस परिणाम का उपयोग करने में रुचि रखने वाले किसी के लिए

from q in context.MyTable
where myListOrArray.Contains(q.someID)
select q;

तब उत्पन्न होने वाली SQL वही है, चाहे आपने MyListOrArray के लिए एक सूची या सरणी का उपयोग किया हो। अब मुझे पता है कि कुछ लोग पूछ सकते हैं कि इस कथन से पहले भी गणना क्यों की गई थी, लेकिन IQueryable बनाम (सूची या सरणी) से उत्पन्न SQL के बीच अंतर है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.