2009-07-31 13 views
14

हाय इन 2 तरीकों लगता है? जब मैं पहली विधि को देखता हूं, तो मुझे लगता है कि सूची के लिए स्मृति आवंटित की गई है, मेरी राय में इसकी आवश्यकता नहीं है। IENumerable विधि मेरे लिए तेज़ी से प्रतीत होती है।सी # सूची <T> बनाम IEnumerable <T> प्रदर्शन सवाल

उदाहरण के लिए, आप

int a = GetProviderForType(myType).Count; 
int b = GetProviderForType1(myType).Count(); 

अब फोन लगता है, एक और मुद्दा है, वहाँ ऊपर इन 2 के बीच एक प्रदर्शन का अंतर है?

आपको क्या लगता है?

+13

सभी का जवाब "जो तेज़ है?" प्रश्न समान हैं: इसे दोनों तरीकों से आजमाएं। एक स्टॉपवॉच प्राप्त करें। तो आप जान लेंगे। –

उत्तर

30

इस विशेष मामले में, IEnumerable<T> फ़ॉर्म का उपयोग करके अधिक कुशल होगा, क्योंकि आप केवल को गिनती जानने की आवश्यकता है। यदि आपको आवश्यकता नहीं है तो डेटा को स्टोर करने, बफर आदि का आकार बदलने में कोई बात नहीं है।

यदि आपको किसी भी कारण से परिणामों का फिर से उपयोग करने की आवश्यकता है, तो List<T> फ़ॉर्म अधिक कुशल होगा।

ध्यान दें कि दोनों Count() विस्तार विधि और Count संपत्ति Count() चेकों के कार्यान्वयन के रूप में अगर लक्ष्य अनुक्रम ICollection<T> लागू करता है और यदि ऐसा है तो Count संपत्ति का उपयोग करता है देखने के लिए List<T> के लिए योग्य होंगे।

एक अन्य विकल्प जो होना चाहिए भी अधिक कुशल (हालांकि सिर्फ), जो एक प्रतिनिधि लेता Count का अधिभार कॉल करने के लिए होगा:

private int GetProviderCount(Type type) 
{ 
    return _objectProviders.Count(provider => 
     (provider.Key.IsAssignableFrom(type) 
     || type.IsAssignableFrom(provider.Key)) 
     && provider.Value.SupportsType(type)); 
} 

यही द्वारा किए गए indirections के अतिरिक्त स्तर से बचने जाएगा Where और Select खंड।

(मार्क कहते हैं, डेटा की थोड़ी मात्रा के लिए प्रदर्शन अंतर शायद वैसे भी नगण्य हो जाएगा।)

+0

मुझे लगता है कि आपको इस मामले में –

+0

दोह - एक निश्चित रूप से एक int वापस करना चाहिए। फिक्स्ड, धन्यवाद :) –

+2

आपके सभी उत्तरों ने वास्तव में मेरी मदद की है, लेकिन मुझे लगता है कि इस सब कुछ का उल्लेख है, इसलिए मैं इसे स्वीकार करता हूं। धन्यवाद! –

4

इस तरह के प्रश्नों का सटीक उत्तर कई कारकों के आधार पर भिन्न हो सकता है, और सीएलआर विकसित होने के साथ आगे बढ़ सकता है। सुनिश्चित करने का एकमात्र तरीका यह मापना है - और ध्यान रखें कि अगर ऑपरेशन की तुलना में अंतर छोटा होता है तो यह दिखाई देगा, तो आपको इसे लिखने का सबसे अधिक पढ़ने योग्य, रखरखाव तरीका चुनना चाहिए।

और उस नोट पर, आप भी करके देख सकते हैं:

private IEnumerable<IObjectProvider> GetProviderForType1(Type type) 
{ 
    return _objectProviders.Where(provider => 
        provider.Key.IsAssignableFrom(type) || 
        type.IsAssignableFrom(provider.Key)) && 
        provider.Value.SupportsType(type)) 
          .Select(p => p.Value); 
} 

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

4

इस सवाल का एक महत्वपूर्ण भाग "कितना बड़ा डेटा है" क्या है? कितनी पंक्तियां ...

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

हालांकि, यह विशाल डेटा वॉल्यूम तक स्केल नहीं करता है; ऐसा लगता है कि आपका प्रदाता हजारों इंटरफेस का समर्थन करता है, इसलिए मैं यह नहीं कहूंगा कि यह आवश्यक है इस मॉडल पर जाने के लिए - लेकिन यह काफी हद तक चोट नहीं पहुंचाएगा।

बेशक

, आप LINQ का भी उपयोग कर सकते हैं:

return from provider in _objectProviders 
     where provider.Key.IsAssignableFrom(type) ... 
     select provider.Value; 

यह भी कवर के तहत आस्थगित yield दृष्टिकोण है ...

2

IEnumerable और IList के बीच मुख्य अंतर:

IENumerable: कार्यान्वयन MoveNext, रीसेट करें, वर्तमान तरीके प्राप्त करें और रिकॉर्ड्स के माध्यम से को Iterate करने के लिए IENumerator का एक प्रकार देता है।

IList: IENumerable इंटरफ़ेस का खुलासा करता है साथ ही साथ यह गैर-जेनेरिक ऑब्जेक्ट्स का भी संग्रह होता है जो इंडेक्स के माध्यम से एक्सेस किया जा सकता है ताकि आईनेमेरेबल + आईसीओलेक्शन (डेटा का मैनिपुलेशन) और जोड़, निकालें, डालें (विशिष्ट इंडेक्स पर) IList द्वारा लागू उपयोगी तरीकों।

अपना कोड इन माई ओपिनियन में देखने के बाद आईन्यूमेरेबल अधिक कुशल है लेकिन वापसी सूची भी उपयोगी है यदि आप डेटा के साथ कुछ हेरफेर करना चाहते हैं और यदि आप डेटा के माध्यम से आईटरेट करना चाहते हैं तो आईन्यूमेरेबल बेहतर है।

+1

गलत। IENumerable सिर्फ एक विधि है। एक इटरेटर लौटाना एक सूची बनाने के लिए काफी अधिक कुशल है। – SLaks

+1

एक और संभावना एक प्रकार को वापस करना होगा जो 'आईसीओलेक्शन' (गैर-जेनेरिक!) को केवल पढ़ने के फैशन के साथ-साथ 'आईनेमेरेबल ' और संभवतः 'आईसीओलेक्शन ' लागू करता है। यदि एक वर्ग जो 'आईनेमेरेबल ' लागू करता है, तो 'आईसीओलेक्शन' या 'आईसीओलेक्शन ' लागू करता है, 'IENumerable 'के लिए' गणना' एक्सटेंशन विधि 'उन इंटरफेस में से किसी एक की गणना संख्या का उपयोग करेगा। अन्यथा इसे गिनने के लिए सभी वस्तुओं को गिनना होगा। ध्यान दें कि गैर-जेनेरिक रूप इस उद्देश्य के लिए थोड़ा अधिक उपयोगी है क्योंकि ... – supercat

+1

... एक 'आईनीमेशन ' का उपयोग 'आईनीमेशन ' के रूप में किया जा सकता है, लेकिन 'आईसीओलेक्शन ' का उपयोग 'आईसीओलेक्शन' के रूप में नहीं किया जा सकता '। यदि एक दिनचर्या जो 'एननीमेशन ' की अपेक्षा करता है उसे कक्षा का उदाहरण दिया गया था जो 'आईसीओलेक्शन ' लागू करता है लेकिन गैर-जेनेरिक 'आईसीओलेक्शन' नहीं, तो यह जानने का कोई तरीका नहीं होगा कि संग्रह को 'आईसीओलेक्शन ' पर डाला जाना चाहिए गिनती पाएं यदि वर्ग गैर-जेनेरिक 'आईसीओलेक्शन' लागू करता है, हालांकि, कोड जो 'IENumerable ' की अपेक्षा करता है उसे कोई परेशानी नहीं होगी। – supercat

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