2011-10-20 12 views
6

का एकाधिक गणना मुझे पता है कि आईन्यूमेरेबल पर कई बार चर्चा की गई है लेकिन मुझे अपने विशिष्ट प्रश्न का उत्तर नहीं मिला, इसलिए मैं इसे एक नए प्रश्न के रूप में ला रहा हूं।आईन्यूमेरेबल

कोड का निम्न भाग पर विचार करें:

static void Main(string[] args) 
    { 

     List<string> testList = new List<string> {"Test", "Test1", "Test1"}; 
     IEnumerable<string> filtered = testList.Where(x => x == "Test1"); 

     DoSomeWork(filtered); 
     DoSomeMoreWork(filtered); 
    } 

    public static void DoSomeWork(IEnumerable<string> items) 
    { 
     foreach (var item in items) 
     { 
      Console.WriteLine("do some work"); 
     } 
    } 

    public static void DoSomeMoreWork(IEnumerable<string> items) 
    { 
     foreach (var item in items) 
     { 
      Console.WriteLine("do some more work"); 
     } 
    } 

मैं सही हूँ, कि यह न केवल दो दो बार पुनरावृति करने के लिए "फ़िल्टर किए गए" आइटम, लेकिन वास्तव में आइटम का कारण बनता है "testList" में? इसलिए, इस बात पर विचार करते हुए कि "टेस्टलिस्ट" 10000 वस्तुओं के साथ एक बड़ी सूची थी और "फ़िल्टर" इसे 10 आइटम तक कम कर देता है, यह एक सूची "फ़िल्टर" करने के लिए और अधिक चालाक होगा (उर्फ उपयोग var और केवल अंत में ToList() संलग्न करें)

संपादित करें: यह सबसे शर्मनाक सवाल है जिसे मैंने कभी भी पूछा है। मुझे पता था कि उदाहरण के लिए एक IQueryable पुनरावृत्ति करना बुरा होगा क्योंकि इससे डीबी से डेटा दो बार प्राप्त होगा। हालांकि मुझे स्मृति सूचियों में बिल्कुल यकीन नहीं था। मैं अगर मैं ;-)

उत्तर

0

सूची ultimatly IEnumrable से विरासत है निम्नलिखित निर्माता avaialble का उपयोग कर इस

public class List<T> : IList<T>, ICollection<T>, 
    IEnumerable<T>, IList, ICollection, IEnumerable 

एक और बात आप IEnurable की सूची बना सकते हैं की जांच कर सकता सवाल हटाना होगा

public List(
    IEnumerable<T> collection 
) 

EDIT

derivedi.e फ़िल्टर की गई सूची दोनों विधियों द्वारा दो बार पुनरावृत्त हो जाती है लेकिन अपील अंत में nd.ToList() विधि।

IEnumerable<string> filtered = testList.Where(x => x == "Test1").ToList(); 

http://msdn.microsoft.com/en-us/library/fkbw11z0.aspx

+0

हाँ, मुझे पता है कि। लेकिन सवाल यह है।Do DoomeWork() और DoSomeMoreWork() दोनों बड़ी सूची को फिर से शुरू करने का कारण बनेंगे या वे केवल सबसेट को फिर से सक्रिय करेंगे। – Christoph

+0

@ क्रिस्टोफ - उत्तर अब संपादित किया गया है ..... –

+0

उपयोग करने के लिए बेहतर। ToArray कि इस उपयोग के लिए ToList: सरणी कुछ हद तक अधिक कुशल हैं, लेकिन सबसे महत्वपूर्ण बात यह है कि वे अनावश्यक लचीलापन से बचने, जोड़ने/निकालने की अनुमति नहीं देते हैं (इस प्रकार भ्रम से परहेज करते हैं और कीड़े)। –

1

बड़ी सूची में दो बार दोहराया कर दिया जाएगा। यदि आप इसे नहीं चाहते हैं, तो आप प्रतिबंध को "भौतिक" बना सकते हैं।

var filtered = testList.Where(x => x == "Test1").ToList(); 

और ऐसे कई जवाब हैं जो आपको बताते हैं। आप खोज की है चाहिए बेहतर :-)

0

यह (उर्फ वर का उपयोग करें और बस अंत में ToList() संलग्न)

हाँ, विशेष रूप से में एक सूची बनाने के लिए "फ़िल्टर किए गए" अधिक चतुर हो जाएगा लिंक-टू-एंटिटीज इत्यादि की शर्तें

लिनक के साथ IEnumerable लौटने से भिन्न निष्पादन की अनुमति मिलती है। जब आप अंत में ToList() जोड़ते हैं, तो आपकी सूची वहां वापस आती है।

देखें http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx

7

बड़ी सूची में दो बार दोहराया कर दिया जाएगा। यह जांचने के लिए कि यह वास्तव में करने के लिए आपकी क्वेरी को बदलने होता है:

List<string> testList = new List<string> { "Test", "Test1", "Test1" }; 
IEnumerable<string> filtered = from t in testList 
           where t == "Test1" 
           select t; 

आप फिर 'जहां टी == "Test1" हिस्से पर एक ब्रेकपाइंट सेट करते हैं, आपको लगता है कि डीबगर दोनों पुनरावृत्तियों के लिए इस लाइन हिट देखेंगे।

+0

आह, हाँ। ये सही है। संकेत के लिए धन्यवाद! – Christoph