संशोधित बंद करने के लिए प्रवेश


316
string [] files = new string[2];
files[0] = "ThinkFarAhead.Example.Settings.Configuration_Local.xml";
files[1] = "ThinkFarAhead.Example.Settings.Configuration_Global.xml";

//Resharper complains this is an "access to modified closure"
for (int i = 0; i < files.Length; i++ )
{
    // Resharper disable AccessToModifiedClosure
    if(Array.Exists(Assembly.GetExecutingAssembly().GetManifestResourceNames(),
    delegate(string name) { return name.Equals(files[i]); }))
         return Assembly.GetExecutingAssembly().GetManifestResourceStream(files[i]);
    // ReSharper restore AccessToModifiedClosure
}

ऊपर ठीक काम करने लगता है, हालांकि ReSharper शिकायत करता है कि यह "संशोधित क्लोजर तक पहुंच" है। क्या कोई इसे स्पष्ट कर सकता है?

(यह विषय यहां जारी रहा )


6
लिंक बाहर है, लेकिन मैं इसे में पाया WebArchive: web.archive.org/web/20150326104221/http://www.jarloo.com/...
एरिक वू

जवाबों:


314

इस मामले में, यह ठीक है, क्योंकि आप वास्तव में प्रतिनिधि को लूप के भीतर निष्पादित कर रहे हैं ।

यदि आप प्रतिनिधि को बचा रहे थे और बाद में इसका उपयोग कर रहे थे, हालाँकि, आप पाएंगे कि सभी प्रतिनिधि फ़ाइलों को एक्सेस करने का प्रयास करते समय अपवादों को फेंक देंगे [i] - वे प्रतिनिधियों के समय इसके मूल्य के बजाय चर को कैप्चर कर रहे हैं। iसृष्टि।

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

अधिक जटिल उदाहरण के लिए इस पृष्ठ के निचले भाग को देखें जहां परिणाम प्रतिसंतुलित हैं।


29

मुझे पता है कि यह एक पुराना प्रश्न है, लेकिन मैंने हाल ही में क्लोजर का अध्ययन किया है और सोचा कि एक कोड नमूना उपयोगी हो सकता है। पर्दे के पीछे, कंपाइलर एक वर्ग उत्पन्न कर रहा है जो आपके फ़ंक्शन कॉल के लिए एक शाब्दिक बंद का प्रतिनिधित्व करता है। यह शायद कुछ इस तरह दिखता है:

private sealed class Closure
{
    public string[] files;
    public int i;

    public bool YourAnonymousMethod(string name)
    {
        return name.Equals(this.files[this.i]);
    }
}

जैसा कि ऊपर उल्लेख किया गया है, आपका कार्य कार्य करता है क्योंकि निर्माण के तुरंत बाद विधेय का आह्वान किया जाता है। कंपाइलर कुछ उत्पन्न करेगा जैसे:

private string Works()
{
    var closure = new Closure();

    closure.files = new string[3];
    closure.files[0] = "notfoo";
    closure.files[1] = "bar";
    closure.files[2] = "notbaz";

    var arrayToSearch = new string[] { "foo", "bar", "baz" };

    //this works, because the predicates are being executed during the loop
    for (closure.i = 0; closure.i < closure.files.Length; closure.i++)
    {
        if (Array.Exists(arrayToSearch, closure.YourAnonymousMethod))
            return closure.files[closure.i];
    }

    return null;
}

दूसरी ओर, यदि आप स्टोर करना चाहते थे और फिर बाद में विधेयकों का आह्वान करते हैं, तो आप देखेंगे कि विधेयकों के लिए हर एक कॉल वास्तव में उसी विधि को बंद वर्ग के उदाहरण पर कॉल करेगा और इसलिए उसी मान का उपयोग करेगा मैं।


4

"फाइल" एक कैप्चर किया गया बाहरी वेरिएबल है क्योंकि इसे अनाम डेलीगेट फ़ंक्शन द्वारा कैप्चर किया गया है। इसका जीवनकाल अनाम प्रतिनिधि समारोह द्वारा बढ़ाया गया है।

बाहरी चर को पकड़ना जब एक बाहरी चर को किसी अनाम फ़ंक्शन द्वारा संदर्भित किया जाता है, तो बाहरी चर को अनाम फ़ंक्शन द्वारा कैप्चर किया गया होता है। आमतौर पर, स्थानीय चर का जीवनकाल ब्लॉक या स्टेटमेंट के निष्पादन तक सीमित होता है, जिसके साथ यह जुड़ा होता है (स्थानीय चर)। हालांकि, एक कैप्चर किए गए बाहरी चर का जीवनकाल कम से कम तब तक बढ़ाया जाता है जब तक कि अनाम फ़ंक्शन से निर्मित प्रतिनिधि या अभिव्यक्ति ट्री कचरा संग्रह के लिए योग्य नहीं हो जाता।

MSDN पर बाहरी चर

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

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