Dans votre cas, tout va bien. C'est l'objet qui publie les événements qui maintient les objectifs des gestionnaires d'événements en direct. Donc, si j'ai:
publisher.SomeEvent += target.DoSomething;
ensuite, publisher
a une référence à l' target
mais pas l'inverse.
Dans votre cas, l'éditeur va être admissibles pour la collecte des ordures (en supposant que il n'y a pas d'autres références), de sorte que le fait qu'il y ait une référence pour le gestionnaire d'événements cibles n'est pas pertinent.
Le cas délicat, c'est quand l'éditeur est de longue durée, mais les abonnés ne veux pas être - dans que cas vous devez vous désabonner les gestionnaires. Par exemple, supposons que vous ayez un service de transmission de données qui vous permet de vous abonner aux notifications asynchrones de la bande passante des changements, et le service de transfert de l'objet est de longue durée. Si nous faisons cela:
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;
(Vous auriez à utiliser un bloc finally pour vous assurer de ne pas laisser couler le gestionnaire d'événements). Si nous n'avons pas de désabonnement, puis l' BandwidthUI
vivraient au moins aussi longtemps que le service de transfert.
Personnellement, j'ai rarement rencontré ce - habituellement, si je m'abonner à un événement, la cible de cet événement de vie au moins aussi longtemps que l'éditeur - une forme durera aussi longtemps que le bouton qui est sur elle, par exemple. Il faut savoir à propos de ce problème potentiel, mais je pense que certaines personnes s'en inquiéter quand ils n'ont pas besoin, car ils ne savent pas qui, autour de la référence.
EDIT: C'est pour répondre à Jonathan Dickinson commentaire. Tout d'abord, regarde la doc de Délégué.Equals(object) qui donnent clairement l'égalité de comportement.
Deuxièmement, voici une courte mais complète du programme est de montrer l'annulation de l'abonnement de travail:
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();
}
}
Résultats:
Raising Foo
Subscriber.FooHandler()
Raising Foo
No handlers
(Testé sur du Mono et du .NET 3.5SP1.)
Modifier:
C'est pour prouver que l'éditeur d'événement peuvent être collectées bien qu'il existe encore des références à un abonné.
using System;
public class Publisher
{
~Publisher()
{
Console.WriteLine("~Publisher");
}
public event EventHandler Foo;
}
public class Subscriber
{
~Subscriber()
{
Console.WriteLine("~Subscriber");
Console.WriteLine("Foo==null ? {0}", Foo == null);
}
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);
}
}
Les résultats de la .NET 3.5SP1; Mono semble se comporter légèrement bizarrement ici. Se regarder dans un intervalle de temps):
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