[C#] IENumerable बनाम सूची - क्या उपयोग करें? वो कैसे काम करते है?



Answers

एक वर्ग जो IEnumerable लागू करता है, आपको foreach सिंटैक्स का उपयोग करने की अनुमति देता है।

मूल रूप से संग्रह में अगला आइटम प्राप्त करने का एक तरीका है। इसे पूरे संग्रह को स्मृति में होने की आवश्यकता नहीं है और यह नहीं जानता कि इसमें कितनी वस्तुएं हैं, foreach केवल अगले आइटम को तब तक जारी रखता है जब तक यह समाप्त न हो जाए।

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

अब List IEnumerable लागू करता है, लेकिन स्मृति में पूरे संग्रह का प्रतिनिधित्व करता है। यदि आपके पास एक .ToList() और आप कॉल करते हैं। .ToList() आप स्मृति में गणना की सामग्री के साथ एक नई सूची बनाते हैं।

आपकी linq अभिव्यक्ति एक गणना लौटाती है, और डिफ़ॉल्ट रूप से जब आप foreach का उपयोग करके पुनरावृत्ति करते हैं तो अभिव्यक्ति निष्पादित होती है। एक .ToList() कथन निष्पादित करता है जब आप .ToList() करते हैं, लेकिन आप इसे जल्द से जल्द उपयोग करने के लिए मजबूर कर सकते हैं। .ToList()

मेरा मतलब यह है कि मेरा क्या मतलब है:

var things = 
    from item in BigDatabaseCall()
    where ....
    select item;

// this will iterate through the entire linq statement:
int count = things.Count();

// this will stop after iterating the first one, but will execute the linq again
bool hasAnyRecs = things.Any();

// this will execute the linq statement *again*
foreach( var thing in things ) ...

// this will copy the results to a list in memory
var list = things.ToList()

// this won't iterate through again, the list knows how many items are in it
int count2 = list.Count();

// this won't execute the linq statement - we have it copied to the list
foreach( var thing in list ) ...
Question

मुझे कुछ संदेह हैं कि एन्युमरेटर्स कैसे काम करते हैं, और LINQ। इन दो साधारण चयनों पर विचार करें:

List<Animal> sel = (from animal in Animals 
                    join race in Species
                    on animal.SpeciesKey equals race.SpeciesKey
                    select animal).Distinct().ToList();

या

IEnumerable<Animal> sel = (from animal in Animals 
                           join race in Species
                           on animal.SpeciesKey equals race.SpeciesKey
                           select animal).Distinct();

मैंने अपनी मूल वस्तुओं के नाम बदल दिए ताकि यह एक अधिक सामान्य उदाहरण जैसा दिखता हो। क्वेरी स्वयं महत्वपूर्ण नहीं है। मैं क्या पूछना चाहता हूं यह है:

foreach (Animal animal in sel) { /*do stuff*/ }
  1. मैंने देखा कि यदि मैं IEnumerable उपयोग करता हूं, जब मैं "सेल" का डीबग और निरीक्षण करता हूं, जो उस मामले में आईनेमरेबल है, इसमें कुछ दिलचस्प सदस्य हैं: "आंतरिक", "बाहरी", "आंतरिककी चयनकर्ता" और "बाहरी के चयनकर्ता", ये अंतिम 2 प्रतिनिधियों के रूप में दिखाई देते हैं। "आंतरिक" सदस्य में "पशु" उदाहरण नहीं हैं, बल्कि "प्रजाति" उदाहरण हैं, जो मेरे लिए बहुत अजीब थे। "बाहरी" सदस्य में "पशु" उदाहरण होते हैं। मुझे लगता है कि दो प्रतिनिधि निर्धारित करते हैं कि कौन सा जाता है और इससे क्या बाहर निकलता है?

  2. मैंने देखा कि यदि मैं "विशिष्ट" का उपयोग करता हूं, तो "आंतरिक" में 6 आइटम होते हैं (यह गलत है क्योंकि केवल 2 अलग हैं), लेकिन "बाहरी" में सही मान होते हैं। दोबारा, शायद प्रतिनिधि पद्धतियां इसे निर्धारित करती हैं लेकिन यह Inumerable के बारे में मुझे कुछ और पता है।

  3. सबसे महत्वपूर्ण बात यह है कि दो विकल्पों में से कौन सा सर्वश्रेष्ठ प्रदर्शन-वार है?

बुराई सूची रूपांतरण। .ToList() माध्यम से?

या शायद सीधे गणनाकर्ता का उपयोग कर?

यदि आप कर सकते हैं, तो कृपया थोड़ा सा समझाएं या कुछ लिंक फेंक दें जो IENumerable के इस उपयोग को समझाते हैं।




IENumerable का लाभ स्थगित निष्पादन (आमतौर पर डेटाबेस के साथ) है। जब तक आप डेटा के माध्यम से वास्तव में लूप नहीं करते हैं तब तक क्वेरी निष्पादित नहीं की जाएगी। यह एक प्रश्न है जब तक इसकी आवश्यकता नहीं है (उर्फ आलसी लोडिंग)।

यदि आप ToList को कॉल करते हैं, तो क्वेरी निष्पादित की जाएगी, या "भौतिक" जैसा कि मैं कहना चाहूंगा।

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




एहसास करने की सबसे महत्वपूर्ण बात यह है कि, लिंक का उपयोग करके, क्वेरी का मूल्यांकन तुरंत नहीं किया जाता है। यह केवल परिणामी IEnumerable<T> माध्यम से पुनरावृत्ति के हिस्से के रूप में चलाया जाता है - यही वह अजीब प्रतिनिधि कर रहा है।

तो, पहला उदाहरण ToList को कॉल करके क्वेरी क्वेरी को तुरंत सूची में डालकर क्वेरी का मूल्यांकन करता है।
दूसरा उदाहरण एक IEnumerable<T> है जिसमें बाद में क्वेरी चलाने के लिए आवश्यक सभी जानकारी होती है।

प्रदर्शन के संदर्भ में, जवाब यह निर्भर करता है । यदि आपको परिणामों को एक बार में मूल्यांकन करने की आवश्यकता है (कहें, आप उन संरचनाओं को म्यूट कर रहे हैं जिन्हें आप बाद में पूछताछ कर रहे हैं, या यदि आप IEnumerable<T> लंबे समय तक लेने के लिए पुनरावृत्ति नहीं चाहते हैं) सूची का उपयोग करें । अन्यथा एक IEnumerable<T> उपयोग करें। डिफॉल्ट को दूसरे उदाहरण में ऑन-डिमांड मूल्यांकन का उपयोग करना चाहिए, क्योंकि आमतौर पर कम स्मृति का उपयोग करता है, जब तक कि सूची में परिणामों को संग्रहीत करने का कोई विशिष्ट कारण न हो।




मैं एक दुरुपयोग की अवधारणा साझा करूंगा कि मैं एक दिन में गिर गया:

var names = new List<string> {"mercedes", "mazda", "bmw", "fiat", "ferrari"};

var startingWith_M = names.Where(x => x.StartsWith("m"));

var startingWith_F = names.Where(x => x.StartsWith("f"));


// updating existing list
names[0] = "ford";

// Guess what should be printed before continuing
print( startingWith_M.ToList() );
print( startingWith_F.ToList() );

अपेक्षित परिणाम

// I was expecting    
print( startingWith_M.ToList() ); // mercedes, mazda
print( startingWith_F.ToList() ); // fiat, ferrari

वास्तविक परिणाम

// what printed actualy   
print( startingWith_M.ToList() ); // mercedes
print( startingWith_F.ToList() ); // ford, fiat, ferrari

व्याख्या

अन्य उत्तरों के मुताबिक, परिणाम का मूल्यांकन ToList या इसी तरह के आमंत्रण विधियों को कॉल करने तक रोक दिया गया था उदाहरण के लिए ToArray

इसलिए मैं इस मामले में कोड को फिर से लिख सकता हूं:

var names = new List<string> {"mercedes", "mazda", "bmw", "fiat", "ferrari"};

// updating existing list
names[0] = "ford";

// before calling ToList directly
var startingWith_M = names.Where(x => x.StartsWith("m"));

var startingWith_F = names.Where(x => x.StartsWith("f"));

print( startingWith_M.ToList() );
print( startingWith_F.ToList() );

चारों ओर खेलें

https://repl.it/E8Ki/0






Links