2015-09-10 15 views
5

अगर मैं इस तरह की एक घटना के लिए एक लैम्ब्डा हुक:जीसी कब एक लैम्ब्डा इकट्ठा कर सकता है जो किसी घटना से जुड़ा हुआ था?

static void DoSomething(Control control) 
{ 
    control.SomeEvent += StaticMethodThatHandlesEvent; 
    Control parentControl = control.Parent; 
    parentControl.Disposed += (sender, args) => 
     { 
      control.SomeEvent -= StaticMethodThatHandlesEvent; 
     }; 
} 

क्या शर्तों के तहत लैम्ब्डा एकत्र किया जा सकता? यदि माता-पिता नियंत्रण एकत्र किया जाता है तो क्या इसे एकत्र किया जाएगा? क्या माता-पिता नियंत्रण एकत्र किया जा सकता है (माना जाता है कि इसे ठीक से निपटाया गया है और मेरे कोड में इसका कोई संदर्भ नहीं है)?

संपादित करें: पूरा कोड एक स्थिर वर्ग में है। क्या यह प्रासंगिक है?

+0

यह इस बात पर निर्भर करता है कि अनाम प्रतिनिधि कैसे लागू किया जाता है। विशेष रूप से, क्या लैम्ब्डा के शरीर में कोई बंद है? – Dennis

+0

मैंने सवाल तय किया, अब यह मेरे करीबी के करीब है। तो मुझे लगता है कि मेरे पास अज्ञात प्रतिनिधि के अंदर केवल 'नियंत्रण' है। – Martze

+1

उस तरह का अनावश्यक नहीं है? निश्चित रूप से यदि अभिभावक नियंत्रण एकत्र किया जाता है, तो बच्चे ईवेंट हैंडलर प्रतिनिधियों समेत भी होगा। आप वास्तव में क्या हल करने की कोशिश कर रहे हैं? ईवेंट हैंडलर केवल वास्तव में "रिसाव" करते हैं जब घटना अपने हैंडलरों से अधिक समय तक जीवित रहती है - शायद ही कभी 'नियंत्रण' के लिए मामला। – Luaan

उत्तर

1

आप इस तरह सवाल है, तो ऐसा करने के लिए गुमनाम तरीकों के बिना कोशिश और देखें कि यह काम करने के लिए क्या आवश्यक है:

internal class Program { 
    private static void Main(string[] args) { 
     DoSomething(new Control() {Parent = new Control()}); 
    } 

    private static void DoSomething(Control control) { 
     control.SomeEvent += MethodThatHandlesEvent; 
     Control parentControl = control.Parent; 
     parentControl.Disposed += new LambdaClass(control).OnDisposed; 
    } 

    private class LambdaClass { 
     private readonly Control _control; 
     public LambdaClass(Control control) { 
      _control = control; 
     } 

     public void OnDisposed(object sender, EventArgs e) { 
      // if MethodThatHandlerEvent is not static, you also need to pass and store reference to the wrapping class 
      _control.SomeEvent -= MethodThatHandlesEvent; 
     } 
    } 


    private static void MethodThatHandlesEvent(object sender, EventArgs e) { 

    } 

    private class Control { 
     public event EventHandler SomeEvent; 
     public event EventHandler Disposed; 
     public Control Parent { get; set; } 
    } 
} 

अब आप एक ही स्थिति है लेकिन किसी भी गुमनाम तरीकों के बिना है। अपने प्रश्न पूछने पर - नियंत्रण और अभिभावक नियंत्रण में पहले से ही एक-दूसरे के संदर्भ हैं, इसलिए पैरेंट नियंत्रण से (लैम्ब्डा क्लास के माध्यम से) पर एक और अप्रत्यक्ष संदर्भ जोड़ना स्थिति में बदलाव नहीं करता है। माता-पिता नियंत्रण और नियंत्रण (और LambdaClass का उदाहरण) दोनों जीसी द्वारा एकत्र किए जाने चाहिए जब जड़ों (स्थानीय, सांख्यिकी और इसी तरह) से उनके लिए कोई अन्य संदर्भ नहीं होगा। .NET जीसी में परिपत्र संदर्भ एकत्र करने में कोई समस्या नहीं है।

1

आप पूरी तरह से बहुत मदद कर रहे हैं। लैम्ब्डा को "डिस्प्ले क्लास" की आवश्यकता होती है, जो नियंत्रण पर संदर्भ को कैप्चर करने के लिए आवश्यक है। घटना को सदस्यता समाप्त करने के लिए बाद में उपयोग किया जाता है। अभिभावक नियंत्रण में डिस्प्ले क्लास ऑब्जेक्ट का डिस्पोजेक्ट इवेंट के माध्यम से संदर्भ होता है और डिस्प्ले क्लास में नियंत्रण का संदर्भ होता है।

तो अभी नियंत्रण और लैम्बडा के लिए डिस्प्ले क्लास ऑब्जेक्ट को तब तक एकत्र नहीं किया जा सकता जब तक कि अभिभावक नियंत्रण एकत्र नहीं किया जा सके। जब आप लैम्ब्डा को हटाते हैं तो नियंत्रण माता-पिता के जीवनकाल के बावजूद, बहुत जल्द एकत्र किया जा सकता है। आप जो चाहते हैं वह है, बाल नियंत्रण हमेशा अपने माता-पिता के नियंत्रण से पहले मर जाते हैं।

कुछ की सदस्यता छोड़ना जरूरी नहीं है, घटना किसी अन्य वस्तु को जीवित नहीं रख सकती है। विधि के बाद अक्सर क्रिस्टल-स्पष्ट होता है क्योंकि MethodThatHandlesEvent() एक स्थिर विधि होनी चाहिए। आवश्यक क्योंकि DoSomething() स्थिर है।

बस लैम्ब्डा हटाएं।

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