2009-10-23 14 views
13

मुझे अभी भी समझ में नहीं आता कि बंद है इसलिए मैंने इन दो उदाहरण पोस्ट किए हैं और मैं जानना चाहता हूं कि ये उदाहरण दोनों बंद हैं या नहीं?क्या ये उदाहरण सी # बंद हैं?

उदाहरण A:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>(); 

Action<string> FilterSubFoldersStartA = 
    s => subFolders. 
     AddRange((new DirectoryInfo(s)).GetDirectories(). 
     Where(d => d.Name.StartsWith("A"))); 

FilterSubFoldersStartA(@"c:\tempa"); 
FilterSubFoldersStartA(@"c:\tempb"); 

उदाहरण B:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>(); 

string filter = "A"; 

Action<string> FilterSubFoldersStartGen = 
    s => subFolders. 
     AddRange((new DirectoryInfo(s)).GetDirectories(). 
     Where(d => d.Name.StartsWith(filter))); 

FilterSubFoldersStartGen(@"c:\tempa"); 

filter = "B"; 

FilterSubFoldersStartGen(@"c:\tempb"); 

उत्तर

6

हां, एक बंद एक समारोह है कि "बचाता है" पर्यावरण से कुछ चर से ज्यादा कुछ नहीं है जिसमें यह परिभषित किया। तो आपके दोनों उदाहरणों में, परिभाषित कार्रवाई subFolders नाम की सूची सहेजती है, जिसे स्थानीय चर के दायरे से बाहर होने के बाद भी फ़ंक्शंस द्वारा संदर्भित किया जा सकता है। दूसरे उदाहरण में filter चर परिभाषित फ़ंक्शन द्वारा भी सहेजा गया है।

एक और अधिक सटीक परिभाषा here

9

आपका दूसरे उदाहरण बंद होने का उपयोग करता है (तकनीकी रूप से आप कह सकते हैं कि संकलक दोनों ही मामलों में एक बंद करने की गणना करता है, लेकिन आप पहले मामले में इसके बारे में उपयोग नहीं करते हैं)।

एक बंद बस "इस कार्य के लिए दृश्यमान सभी चर" है। न कुछ ज्यादा, न कुछ कम। और जाहिर है, दोनों मामलों में, वे चर मौजूद हैं, और संकलक द्वारा निर्धारित किए जाते हैं।

लेकिन जब हम "बंद करने का उपयोग" के बारे में बात करते हैं तो आम तौर पर इसका मतलब यह है कि लैम्ब्डा अभिव्यक्ति उन सभी स्थानीय चरों का उपयोग कर सकती है, जिन्हें वे घोषित कर रहे हैं। वे इसके बंद होने का हिस्सा हैं।

आपके मामले में, d लैम्बडा फ़ंक्शन के लिए केवल पैरामीटर है, और चूंकि आप पहले मामले में इसका उपयोग करते हैं, इसलिए आप वास्तव में बंद होने का लाभ नहीं ले रहे हैं।

दूसरे मामले में, filter लैम्ब्डा अभिव्यक्ति में परिभाषित नहीं है, यह पैरामीटर या कुछ भी नहीं है। यह एक स्थानीय चर है जो उस स्थान पर दिखाई देता है जहां भेड़ का बच्चा घोषित किया जाता है। तो यह लैम्ब्डा के बंद होने का हिस्सा है, जो आपको इसे लैम्ब्डा के शरीर में संदर्भित करने की अनुमति देता है।

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

+2

पहला उदाहरण 'सबफोल्डर्स 'पर बंद हो जाता है, इसलिए यह भी बंद हो जाता है। –

+0

ओह ठीक है, मैंने पहले लैम्ब्डा को भी नोटिस नहीं किया था। मैंने अभी देखा 'डी => ...' एक। आप सही हे। पहला 'उपफोल्डर्स' से अधिक बंद हो जाता है, और दूसरे मामले में, दूसरा लैम्ब्डा 'फ़िल्टर' पर बंद हो जाता है। – jalf

0

दोनों उदाहरण बंद हैं। "ए" अज्ञात विधि में स्थानीय चर उप-फ़ोल्डरों को कैप्चर करता है। "बी" अज्ञात विधि में स्थानीय चर उप-फ़ोल्डर्स और फ़िल्टर कैप्चर करता है। here पर भी एक नज़र डालें।

पीएस यह भी ध्यान रखें कि आप वास्तव में "ए" में बंद करने का उपयोग कर रहे हैं क्योंकि आप उपफोल्डर चर का उपयोग कर रहे हैं।

0

यहां कुछ ऐसा उदाहरण है जो http://www.agileatwork.com/a-proper-closure-in-csharp/ से कुछ है जो आपको जावास्क्रिप्ट के साथ सहज होने पर थोड़ा और परिचित लग सकता है। एक बंदरगाह tax चर के चारों ओर बनाया गया है, इसलिए गणना केवल एक बार की जाती है। यह आंखों पर बिल्कुल आसान नहीं है, लेकिन यह अच्छा है कि आप इस प्रकार की चीज़ सी # में कर सकते हैं।

public class Order 
{ 
    public Order(ITaxCalculator taxCalculator) 
    { 
     CalculateTax = new Func<Func<decimal>>(() => 
     { 
      decimal? tax = null; 
      return() => 
      { 
       if (!tax.HasValue) 
       { 
        tax = taxCalculator.Calculate(this); 
       } 
       return tax.Value; 
      }; 
     })(); 
    } 

    public Func<decimal> CalculateTax { get; set; } 

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