2011-06-01 12 views
8

मैं स्थानीय चर में एक क्रिया संग्रहीत कर रहा हूं, फिर मैं उस स्थानीय चर के दायरे से बाहर होने के बाद उपयोग कर रहा हूं। क्या इसका उपयोग करने से पहले इसे साफ़ करने का खतरा है? यहाँ एक उदाहरण है:एक्शन/लैम्ब्डा एक्सप्रेशन मेमोरी मैनेजमेंट प्रश्न

public List<object> GetMaps() { 
    Action<Customer1, Customer2> baseMap = (Customer1 c1, Customer2 c2) => { 
     c2.FirstName = c1.FirstName; 
    }; 

    var list = new List<object>() { 
     new Action<SpecialCustomer1 c1, SpecialCustomer2 c2>() { 
      baseMap(c1, c2); 
      c2.SpecialProperty = c1.SpecialProperty; 
     }, 
     new Action<SpecialCustomer1 c1, SpecialCustomer2 c2>() { 
      baseMap(c1, c2); 
      c2.SpecialProperty2 = c1.SpecialProperty2; 
     }, 
    }; 

    return list; 
} 

तो, आप इस उदाहरण में देख सकते हैं कि समारोह कार्यों कि फोन baseMap की एक सूची लौटा रहा है। baseMap सिर्फ एक स्थानीय चर है। क्या यह तथ्य है कि इसे .NET के लिए पर्याप्त अन्य क्रियाओं के भीतर बुलाया गया है ताकि इसे साफ न किया जा सके?

उत्तर

11

मैं सी # 4 कल्पना, जो कहते हैं की धारा 5.1.7 का उल्लेख:

स्थानीय चर एक गुमनाम समारोह द्वारा कब्जा कर लिया गया है, तो , इसका जीवनकाल कम से कम गुमनाम समारोह से बनाए गए प्रतिनिधि या अभिव्यक्ति वृक्ष तक फैला हुआ है, साथ ही कब्जे वाले चर के संदर्भ में आने वाली किसी अन्य वस्तु के साथ, कचरा संग्रह के लिए पात्र हैं।

भले ही नियंत्रण स्थानीय के दायरे के अंत से गुज़रता है, स्थानीय का जीवनकाल बढ़ाया जाता है। अभ्यास में हम स्थानीय को बंद करने वाले वर्ग के क्षेत्र में बदलकर और फिर प्रतिनिधि को प्रतिनिधि (या अभिव्यक्ति वृक्ष) में संदर्भित करके जीवित रखते हुए करते हैं।

ध्यान दें कि आप विपरीत समस्या में भाग सकते हैं; कभी कभी बातें लंबे समय तक के लिए की तुलना में आप उन्हें चाहते हैं रहते हैं:

Expensive expensive = new Expensive(); 
Cheap cheap = new Cheap(); 
Action longlived =()=>M(cheap); 
Action shortlived =()=>M(expensive); 

तरीका यह आज सी # में काम करता है दो प्रतिनिधियों के लिए उत्पन्न बंद रहता है दोनों "सस्ते" और "महंगा" जीवित जब तक लंबे समय तक के जीवनकाल - प्रतिनिधि प्रतिनिधि, भले ही लंबे समय से रहने वाले प्रतिनिधि वास्तव में "महंगे" का उपयोग नहीं करते हैं! (वीबी, जेस्क्रिप्ट और बंद होने वाली कई अन्य भाषाओं में भी यह समस्या है।)

हम यहां क्या कर सकते हैं संकलक में इस स्थिति का पता लगाने और दो बंद करने के लिए है। हम इसे सी # के भविष्य के संस्करण के लिए करने पर विचार कर रहे हैं।

5

नहीं, यह खतरे में नहीं है। एक अज्ञात विधि जो उस अज्ञात विधि के बाहर से स्थानीय चर का उपयोग करती है उसे उस क्षेत्र के साथ एक नई कक्षा में संकलित किया जाएगा जो उस स्थानीय चर को सहेजता है और एक विधि जो अज्ञात विधि से मेल खाती है।

class ModifiedClosure 
{ 
    private Action<Customer1, Customer2> _baseMap; 
    public ModifiedClosure(Action<Customer1, Customer2> baseMap) 
    { 
     _baseMap = baseMap; 
    } 

    public void Method(SpecialCustomer1 c1, SpecialCustomer2 c2) 
    { 
     _baseMap(c1, c2); 
     c2.SpecialProperty = c1.SpecialProperty; 
    } 
} 

सूची आरंभीकरण तो कुछ इस तरह दिखेगा::

Action<Customer1, Customer2> baseMap = (c1, c2) => c2.FirstName = c1.FirstName; 

var list = new List<object>() 
{ 
    (Action<SpecialCustomer1, 
      SpecialCustomer2>)(new ModifiedClosure(baseMap).Method), 
    // ... 
}; 

Btw:

आपके मामले में, यह निम्नलिखित की तरह कुछ पैदा करेगा आपका वाक्य रचना थोड़ा बंद है। सूची निर्माण संकलित नहीं होगा। यह इस तरह दिखना चाहिए:

var list = new List<object>() 
{ 
    (Action<SpecialCustomer1, SpecialCustomer2>)((c1, c2) => 
    { 
     baseMap(c1, c2); 
     c2.SpecialProperty = c1.SpecialProperty; 
    }), 
    (Action<SpecialCustomer1, SpecialCustomer2>)((c1, c2) => 
    { 
     baseMap(c1, c2); 
     c2.SpecialProperty2 = c1.SpecialProperty2; 
    }) 
}; 
0

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

1

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

तो नहीं, तुम खतरे में नहीं कर रहे हैं

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