60 votes

Ajout et suppression d'un gestionnaire d'événements anonymes

Je me demandais si cela fonctionnait réellement?

 private void RegisterKeyChanged(T item) 
{
    item.OnKeyChanged += (o, k) => ChangeItemKey((T)o, k);
}

private void UnRegisterKeyChanged(T item) 
{
    item.OnKeyChanged -= (o, k) => ChangeItemKey((T)o, k);
}
 

Comment le compilateur sait-il que les gestionnaires d'événements sont les mêmes? Est-ce même recommandé?

64voto

Kyralessa Points 76456

Il y a une page MSDN qui en parle:

Comment s'Abonner et de se Désabonner à partir d'Événements

Remarque en particulier:

Si vous n'aurez pas à vous désabonner à [sic] un événement plus tard, vous pouvez utiliser le outre opérateur d'affectation (+=) à joindre une méthode anonyme à l' de l'événement.

Et aussi:

Il est important de noter que vous ne peut pas se désinscrire facilement à partir d'un événement si vous avez utilisé un anonyme fonction de vous y inscrire. Pour se désabonner dans ce scénario, il est nécessaire de revenir à l'endroit du code où vous vous inscrire à l'événement, le magasin méthode anonyme dans un délégué variable, puis ajouter le délégué à la manifestation . En général, nous recommandons que vous n'utilisez pas anonyme fonctions pour s'abonner à des événements si vous devez vous désabonner à partir de l'événement à un moment plus tard dans votre code.

6voto

Dan Herbert Points 38336

Si vous avez besoin de vous désabonner d'un gestionnaire d'événement, vous aurez besoin d'avoir une certaine référence à un béton délégué. En regardant Delegate.Equality vous trouverez que les délégués ne sont pas simplement par rapport à l'aide de la référence à l'égalité, mais ce n'est pas grave pour les délégués anonymes.

Pour un délégué anonyme, le compilateur (en gros) crée un nouveau "non anonyme" délégué pour délégué anonyme, même si le délégué organes sont les mêmes. De ce fait, le cadre ne sera pas trouver le délégué de vous désabonner quand vous utilisez l'exemple de code que vous avez donné.

3voto

Noldorin Points 67794

Qui ne fonctionne pas, j'ai peur, car les deux expressions lambda (et délégués) que vous avez déclarés sont en fait des objets différents, et le retour des références différentes. Ainsi, la suppression de la fonction (-=) échouera toujours.

La solution commune à ce problème (là où vous devez supprimer le gestionnaire) est tout simplement de refactoriser le lamba expression dans une bonne méthode. Une alternative est de maintenir une variable de classe pour le gestionnaire d'événement délégué, et ajouter et supprimer des ce, bien que personnellement, je suis pas un fan de lui. (C'est plus de tracas que de créer une méthode normale, si quoi que ce soit.)

2voto

Dan Auclair Points 3063

Je ne crois pas que ça va marcher. Si vous avez vraiment besoin de vous désinscrire d'un événement, vous devez spécifier un gestionnaire d'événement explicite sur lequel vous pourrez ultérieurement vous désinscrire à la place d'un délégué anonyme.

1voto

Codism Points 1324

Si vous vérifiez le document pour Delegate.Equality, vous constaterez qu'ils ne sont pas comparés par référence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X