आपके मामले में, सब कुछ ठीक है। यह ऐसी वस्तु है जो उन घटनाओं को प्रकाशित करती है जो घटना संचालकों के लक्ष्य को जीवित रखती हैं। तो अगर मेरे पास है:
publisher.SomeEvent += target.DoSomething;
फिर publisher
एक संदर्भ है, target
लेकिन दूसरे तरीके से नहीं।
आपके मामले में, प्रकाशक कचरा संग्रहण के लिए पात्र होने जा रहा है (यह मानते हुए कि इसके कोई अन्य संदर्भ नहीं हैं) तो यह तथ्य यह है कि यह घटना हैंडलर लक्ष्यों के लिए एक संदर्भ है अप्रासंगिक है।
मुश्किल मामला तब होता है जब प्रकाशक लंबे समय तक जीवित रहता है लेकिन ग्राहक नहीं बनना चाहते हैं - उस स्थिति में आपको हैंडलर को अनसब्सक्राइब करने की आवश्यकता होती है। उदाहरण के लिए, मान लें कि आपके पास कुछ डेटा ट्रांसफ़र सेवा है, जो आपको बैंडविड्थ परिवर्तनों के बारे में अतुल्यकालिक सूचनाओं की सदस्यता देता है, और स्थानांतरण सेवा ऑब्जेक्ट लंबे समय तक जीवित रहता है। यदि हम ऐसा करते हैं:
BandwidthUI ui = new BandwidthUI();
transferService.BandwidthChanged += ui.HandleBandwidthChange;
// Suppose this blocks until the transfer is complete
transferService.Transfer(source, destination);
// We now have to unsusbcribe from the event
transferService.BandwidthChanged -= ui.HandleBandwidthChange;
(आप वास्तव में इवेंट हैंडलर को लीक नहीं करने के लिए यह सुनिश्चित करने के लिए अंत में ब्लॉक का उपयोग करना चाहते हैं।) यदि हमने सदस्यता समाप्त नहीं की, तो BandwidthUI
कम से कम तब तक जीवित रहेंगे जब तक कि स्थानांतरण सेवा नहीं होगी।
व्यक्तिगत रूप से मैं इस पर शायद ही कभी आता हूं - आमतौर पर अगर मैं किसी घटना की सदस्यता लेता हूं, तो उस घटना का लक्ष्य कम से कम तब तक रहता है जब तक कि प्रकाशक - एक फॉर्म तब तक रहेगा जब तक कि बटन उस पर है, उदाहरण के लिए। यह इस संभावित मुद्दे के बारे में जानने के लायक है, लेकिन मुझे लगता है कि कुछ लोगों को इसके बारे में चिंता होती है जब उन्हें ज़रूरत नहीं होती, क्योंकि वे नहीं जानते कि किस तरह से संदर्भों को गोल किया जाता है।
EDIT: यह जोनाथन डिकिंसन की टिप्पणी का जवाब देने के लिए है। सबसे पहले, डेलिगेट के लिए डॉक्स देखें। ईक्ल्स (ऑब्जेक्ट) जो स्पष्ट रूप से समानता का व्यवहार देते हैं।
दूसरी बात, सदस्यता समाप्त करने के लिए यहाँ एक छोटा लेकिन पूरा कार्यक्रम काम कर रहा है:
using System;
public class Publisher
{
public event EventHandler Foo;
public void RaiseFoo()
{
Console.WriteLine("Raising Foo");
EventHandler handler = Foo;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
else
{
Console.WriteLine("No handlers");
}
}
}
public class Subscriber
{
public void FooHandler(object sender, EventArgs e)
{
Console.WriteLine("Subscriber.FooHandler()");
}
}
public class Test
{
static void Main()
{
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.Foo += subscriber.FooHandler;
publisher.RaiseFoo();
publisher.Foo -= subscriber.FooHandler;
publisher.RaiseFoo();
}
}
परिणाम:
Raising Foo
Subscriber.FooHandler()
Raising Foo
No handlers
(मोनो और .NET 3.5SP1 पर परीक्षण किया गया।)
आगे संपादित करें:
यह साबित करना है कि एक घटना प्रकाशक को एकत्र किया जा सकता है जबकि एक ग्राहक के संदर्भ अभी भी हैं।
using System;
public class Publisher
{
~Publisher()
{
Console.WriteLine("~Publisher");
Console.WriteLine("Foo==null ? {0}", Foo == null);
}
public event EventHandler Foo;
}
public class Subscriber
{
~Subscriber()
{
Console.WriteLine("~Subscriber");
}
public void FooHandler(object sender, EventArgs e) {}
}
public class Test
{
static void Main()
{
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.Foo += subscriber.FooHandler;
Console.WriteLine("No more refs to publisher, "
+ "but subscriber is alive");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("End of Main method. Subscriber is about to "
+ "become eligible for collection");
GC.KeepAlive(subscriber);
}
}
परिणाम (.NET 3.5SP1 में; मोनो थोड़ा अजीब तरह से व्यवहार करता प्रतीत होता है। कुछ समय में दिखेगा)
No more refs to publisher, but subscriber is alive
~Publisher
Foo==null ? False
End of Main method. Subscriber is about to become eligible for collection
~Subscriber