2009-07-21 11 views
0

Peut-être une question stupide, mais ..Est-ce dangereux? A propos des événements

Dans mon code, j'utilise la construction suivante à plusieurs endroits. Donc, je veux faire quelque chose initialement, et faire la même chose quand la propriété change dans le futur.

Maintenant, MyFunction() est appelée plusieurs fois pendant l'exécution de mon programme. Le délégué que j'attribue à PropertyChanged sera-t-il ajouté chaque fois qu'il passera par cette méthode? (consommer plus de mémoire à chaque itération et ralentir le programme) Ou est le compilateur/runtime assez intelligent pour comprendre que je devrais être ajouté la première fois ..? Et si oui, comment cela fonctionne-t-il?

+0

Ce n'est peut-être pas un problème pour vous, mais avec cette syntaxe, il n'est pas possible de désabonner l'eventhandler anonyme de cet événement, ce qui peut entraîner des problèmes de mémoire. Je recommande d'écrire la fonction, et attachez simplement le eventhandler avec le + new eventhandler (fonction); –

Répondre

3

La plupart des autres réponses suggèrent que vous devriez vérifier si l'événement est PropertyChangednull pour empêcher l'ajout de plusieurs auditeurs. Un problème avec cette solution est que PropertyChanged peut être non null si d'autres parties du code écoutent le même événement mais pour une autre propriété, comme ceci.

void AnotherFunction() 
{ 
    myClass.PropertyChanged += (s,e) => { 
    if (e.PropertyName == "anotherProperty") { 
     DoSomethingElse(myClass.anotherProperty); 
    } 
    } 
} 

Une meilleure solution, à mon avis, serait de maintenir un drapeau booléen qui est d'abord faux, et que la valeur true lorsque MyFunction est appelé. Ensuite, vérifiez ce drapeau si vous devez ajouter le gestionnaire d'événements.

+0

Merci, réponse la plus complète –

4

Le compilateur ne peut pas connaître votre intention ... il attachera fidèlement le gestionnaire d'événements à chaque appel à MyFunction(). Examinez-le de cette façon: le compilateur ne peut pas savoir que les variables de référence (par exemple, myclass) dans votre fonction se réfèrent aux mêmes instances d'objets auxquels vous avez déjà attaché des gestionnaires. Il ne peut pas non plus savoir que vous n'avez pas détaché le gestionnaire ailleurs entre les appels. Il ne peut pas faire d'hypothèses comme celle-ci.

Cependant, vous pouvez restructurer votre code de sorte que le gestionnaire ne soit attaché qu'une seule fois. Étant donné que d'autres consommateurs peuvent s'abonner à l'événement PropertyChanged, vous devez conserver un état indépendant pour savoir si vous êtes abonné ou non. Par exemple:

if(!haveSubscribedToPropertyChanged) { 
    myClass.PropertyChanged += (s,e) => { 
      if (e.PropertyName == "myProperty") { 
       DoSomething(myClass.myProperty); 
      } 
     } 
     haveSubscribedToPropertyChanged = true; 
     } 
+0

Merci. Un problème ici est aussi que myClass est un singleton qui peut également être consulté à partir d'autres méthodes. Alors d'autres peuvent ajouter qu'ils ont aussi des délégués. J'ai besoin de trouver quelque chose pour cela aussi. –

+0

La solution de vérification de null n'est pas viable pour un événement PropertyChanged, car d'autres parties du code peuvent utiliser le même événement pour écouter les changements de propriétés différentes. Voir ma réponse pour une solution différente: http://stackoverflow.com/questions/1158849/is-this-dangerous-about-events/1158930#1158930 –

+0

Bon point. Je vais réviser ma réponse. – LBushkin

Questions connexes