Senin durumunda her şey yolunda. Olay işleyicilerinin hedeflerini canlı tutan olayları yayınlayan nesnedir . Yani eğer sahipsem:
publisher.SomeEvent += target.DoSomething;
o publisher
zaman bir referansı vardır, target
ancak tersi yoktur.
Sizin durumunuzda, yayıncı çöp toplama için uygun olacaktır (buna başka referans olmadığı varsayılarak), bu nedenle olay işleyici hedeflerine bir referans olması gerçeği alakasızdır.
Zor durum, yayıncının uzun ömürlü olduğu ancak abonelerin olmak istemediği durumdur - bu durumda işleyicileri aboneliğinizi iptal etmeniz gerekir. Örneğin, bant genişliği değişiklikleri hakkında eşzamansız bildirimlere abone olmanıza izin veren bir veri aktarım hizmetiniz olduğunu ve aktarım hizmeti nesnesinin uzun ömürlü olduğunu varsayalım. Bunu yaparsak:
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;
(Aslında olay işleyicisini sızdırmadığınızdan emin olmak için bir nihayet bloğu kullanmak istersiniz.) Eğer abonelikten çıkmazsak, o zaman BandwidthUI
en azından transfer hizmeti kadar yaşar.
Şahsen buna nadiren rastlarım - genellikle bir etkinliğe abone olursam, o etkinliğin hedefi en azından yayıncı kadar yaşar - bir form, örneğin üzerindeki düğme kadar dayanır. Bu potansiyel konu hakkında bilgi sahibi olmaya değer, ancak bence bazı insanlar ihtiyaç duymadıkları zaman endişeleniyor çünkü referansların hangi yöne gittiğini bilmiyorlar.
DÜZENLEME: Bu, Jonathan Dickinson'un yorumuna cevap vermek içindir. İlk olarak, eşitlik davranışını açıkça veren Delegate.Equals (nesne) belgelerine bakın .
İkinci olarak, işte abonelik iptalinin çalıştığını gösteren kısa ama eksiksiz bir program:
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();
}
}
Sonuçlar:
Raising Foo
Subscriber.FooHandler()
Raising Foo
No handlers
(Mono ve .NET 3.5SP1'de test edilmiştir.)
Daha fazla düzenleme:
Bu, bir aboneye yönelik referanslar varken bir etkinlik yayıncısının toplanabileceğini kanıtlamak içindir.
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);
}
}
Sonuçlar (.NET 3.5SP1'de; Mono burada biraz tuhaf davranıyor gibi görünüyor. Bunu bir süre araştıracak):
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