web-dev-qa-db-fra.com

Dois-je toujours déconnecter les gestionnaires d'événements dans la méthode Dispose?

Je travaille en C # et mon lieu de travail a des normes de code. L'un d'eux est que chaque gestionnaire d'événements que nous connectons (tel que KeyDown) doit être déconnecté dans la méthode Dispose. Y a-t-il une bonne raison à cela?

40
No Idea For Name

À moins que vous ne vous attendiez à ce que l'éditeur de l'événement survive à l'abonné, il n'y a aucune raison de supprimer le gestionnaire d'événements, non.

C'est l'un de ces sujets où la tradition populaire a grandi. Il faut vraiment y penser en termes normaux: l'éditeur (par exemple le bouton) a une référence à l'abonné. Si l'éditeur et l'abonné seront éligibles à la collecte des ordures en même temps de toute façon (comme cela est courant) ou si l'éditeur sera éligible à la collecte des ordures plus tôt, alors il n'y a pas de problème de GC.

Les événements statiques provoquent un problème de GC car ils sont en fait un éditeur à durée de vie infinie - je découragerais complètement les événements statiques, si possible. (Je les trouve très rarement utiles.)

L'autre problème possible est si vous voulez explicitement arrêter d'écouter les événements parce que votre objet se comportera mal si l'événement est déclenché (par exemple, il essaiera d'écrire dans un flux fermé). Dans ce cas, oui, vous devez supprimer le gestionnaire. C'est probablement le cas dans le cas où votre classe implémente déjà IDisposable. Il serait inhabituel - mais pas impossible - que cela vaille la peine d'implémenter IDisposablejuste pour supprimer les gestionnaires d'événements.

71
Jon Skeet

J'ai eu une fuite majeure GDI dans mon application si je ne désinscrivais pas les gestionnaires d'événements dans Dispose () d'un contrôle utilisateur qui était créé et détruit dynamiquement. J'ai trouvé ce qui suit dans le Aide de Visual Studio 2013, dans le Guide de programmation C #. Notez ce que j'ai mis en italique:

Comment: s'abonner et se désinscrire d'événements

... snip ... Se désabonner Pour empêcher votre gestionnaire d'événements d'être appelé lorsque l'événement est déclenché, désabonnez-vous de l'événement. Afin d'éviter les fuites de ressources, vous devez vous désabonner des événements avant de vous débarrasser d'un objet abonné. Jusqu'à ce que vous vous désabonniez d'un événement, le délégué de multidiffusion qui sous-tend l'événement dans l'objet de publication a une référence au délégué qui encapsule le gestionnaire d'événements de l'abonné. Tant que l'objet de publication contient cette référence, la récupération de place ne supprimera pas votre objet abonné.

Notez que dans mon cas, l'éditeur et l'abonné étaient dans la même classe et les gestionnaires ne sont pas statiques.

11
JonP