2009-06-05 17 views
7

चलो कहते हैं कि मैं एक वर्ग एक जो एक्स अब कहा जाता है मैं एक वर्ग बी है और एक विधि में मैं एक करने के लिए एक उदाहरण हो और बी में एक हैंडलर को घटना बाँध एक ईवेंट सक्रिय कर सकते हैं करते हैं:ईवेंट हैंडलर से सुरक्षित तरीके से कैसे छुटकारा पाएं?

public void BindEvent(A a) 
{ 
    a.X += AEventHandler; 
} 

मेरे पास इसके बारे में तीन प्रश्न हैं।

  • यह सच है कि जब मैं अब सेट शून्य पर बी उदाहरण के संदर्भ में है, यह कचरा एकत्र नहीं किया जाएगा के बाद से कचरा कलेक्टर सोचता है कि यह अभी भी उपयोग (एक प्रकार से बेकार ध्यान में रखते हुए है और संभावित रूप से की प्रति दखल स्मृति में बी)।

  • मेरे पास एक और ऑब्जेक्ट सी (कक्षा सी) के बारे में क्या है जिसमें मेरे पास ए ("this.a = new A()") का संदर्भ है। फिर मैं "बी। बाइंडवेन्ट (यह.ए)" कहता हूं, और सी में मैंने संदर्भ को एक शून्य ("this.a = null") पर सेट किया है। क्या यह ए की याद में स्मृति की प्रतिलिपि रखेगा क्योंकि यह बी में घटना के माध्यम से संदर्भित है?

  • यदि कोई या दोनों ऊपर से सत्य हैं, तो मैं इन मुद्दों को सबसे अच्छी तरह से कैसे रोक सकता हूं? अगर मेरे पास ईवेंट हैंडलर की पूरी सूची है ("ए। सोमेन्ट + = कुछ विधि" जैसी 10 लाइनें कहें) क्या मुझे उन्हें फिर से साफ करना चाहिए ("ए.मेमवेन्ट - = कुछ विधि")। कोड में किस समय या स्थान पर मुझे इन चीजों को करना चाहिए?

वैसे यह थोड़ा अस्पष्ट हो गया है लेकिन मुझे यकीन नहीं है कि बेहतर तरीके से कैसे समझाया जाए। अगर मुझे कुछ और विस्तृत जानकारी देने की ज़रूरत है तो कृपया एक टिप्पणी छोड़ दें।

उत्तर

8

इसलिए: A प्रकाशक है और B ग्राहक है?

पहले बुलेट: अगर BAEventHandler साथ उदाहरण है - तो यह उपयोग में अभी भी है, इसलिए नहीं, यह एकत्र नहीं किया जाएगा जब तक कि a उदाहरण नहीं पहुंचा जा सकता है।

दूसरी बुलेट: हुह? (फिर से पढ़ा जाएगा ...) यदि A और B उदाहरण दोनों पहुंच योग्य नहीं हैं, तो वे कचरा एकत्र होंगे; घटना कोई फर्क नहीं पड़ता। यदि A पहुंच योग्य है, तो B जीवित रहेगा। हालांकि, घटना सदस्यता कभीA जीवित रहता है; यह एक तरीका है ... AB जीवित रख सकता है, लेकिन BA जीवित नहीं रखता है। क्या यह इसे कवर करता है?

तीसरी गोली: ज्यादातर मामलों में, दोनों चीजों में समान जीवन व्यतीत होता है, इसलिए यह कोई मुद्दा नहीं है। यह केवल एक मुद्दा बन जाता है यदि घटना प्रकाशित करने वाली चीज़ हैंडलरों के साथ चीजों की तुलना में बहुत अधिक समय तक रहती है। इस मामले में, आपको बस अपने आप को बाद में धार्मिक रूप से साफ करने की आवश्यकता है - उदाहरण के लिए: a.X -= AEventHandler। विशेष रूप से, इस कारण से static घटनाएं बुरा हैं।

4

आपको क्लास इंस्टेंस को नष्ट करने से पहले ईवेंट हैंडलर को वास्तव में अनबिंड करना चाहिए। (एक उदाहरण के रूप में अपने कोड का उपयोग करना।)

public void UnbindEvent(A a) 
{ 
    a.X -= AEventHandler; 
} 

मैं भी पूछना होगा, तुम क्यों वर्ग चर सेट कर रहे हैं शून्य पर?

2
  1. सही।
  2. सही।
  3. आप इस व्यवहार को क्यों रोकना चाहते हैं? इस प्रकार जीसी को काम करने के लिए डिज़ाइन किया गया है। यदि आपको प्रत्येक वस्तु को तोड़ने पर कुछ साफ करने की ज़रूरत है, तो निपटान पैटर्न का उपयोग करें।
+0

मुझे पूरा यकीन है कि 2 गलत है। सबसे पहले, घटना * कभी भी प्रकाशक ('ए') को जीवित नहीं रखती - और दूसरा, कुछ भी 'ए' को देख नहीं सकता है ... इसलिए डेटा डिस्कनेक्ट और एकत्र हो गया है। –

+0

दोह! मुझे सही साबित होना है। :-) –

1

हां, घटना संदर्भ हैं, यदि आप पंजीकरण नहीं करते हैं, तो ईवेंट हैंडलर को लागू करने वाली वस्तु कचरा नहीं होगी।

आप ऐसा कर सकते हैं:

सभी पंजीकृत ईवेंट निकालें, अगर एक जानता है जब वे अब उपयोग नहीं किया जाता।

class A 
{ 
    // clearing all registrations 
    private void ClearEvents() 
    { 
    X = null; 
    } 
} 

या यदि आप बी को जानते हैं कि यह अब इसका उपयोग नहीं करता है तो आप बी में पंजीकरण नहीं करते हैं। पंजीकरण करने में सक्षम होने के लिए आपको एक संदर्भ रखना होगा।

आप आईडीस्पोज़ेबल को भी कार्यान्वित कर सकते हैं।

class B : IDisposable 
{ 
    private A registeredToA; 

    public void BindEvent(A a) 
    { 
    registeredToA = a; 
    registeredToA.X += AEventHandler; 
    } 

    public void Dispose() 
    { 
    registeredToA.x -= AEventHandler; 
    } 
} 

यह आपके कोड में एक तोड़ने वाला परिवर्तन है, क्योंकि बी को हमेशा निपटान करने की आवश्यकता है।

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