2010-06-03 6 views
9

Je viens de me rendre compte que je ne comprends pas entièrement pourquoi dans .NET vous assignez des événements en utilisant un symbole + =.Comment les événements sont assignés dans .NET

Je compris cela hier quand je avais besoin de supprimer un événement et sans penser que je faisais

someobject.onsomeevent += null 

pensée qui simplement supprimer l'événement que j'avais déjà affecté.

Après enquête, je compris que je devais

someobject.onsomeevent -= someeventmethod; 

Après ceci comprendre, je me suis aperçu que je ne comprends pas comment les méthodes d'événements sont attribués dans .NET.

J'ai donc quelques questions:

Premièrement, est-ce que cela signifie que je peux faire

someobject.onsomeevent += someeventmethod; 
someobject.onsomeevent += someeventothermethod; 

Si oui, quand onsomeevent se produit seront-ils tous les deux se frapper, et dans l'ordre spécifié ou simultanément?

En outre, comment puis-je déterminer quelles méthodes d'événement sont déjà affectées à someobject.onsomeevent? Deuxièmement, existe-t-il un moyen d'enregistrer les méthodes d'événements dans une classe, de les supprimer de someobject.onsomeevent et de les réassigner après que d'autres procédures qui déclenchent normalement l'événement soient terminées?

+1

Pour confusion, vous devriez essayer long (.NET 1.x) forme: 'someobject.onsomeevent - = new Eventhandler (someeventmethod);' –

+0

Tant de bonnes réponses! Merci a tous! – Matt

Répondre

3

Première question: Oui, vous pouvez le faire, à condition que les signatures de méthode soient compatibles avec le type délégué de l'événement.

Deuxième question: Oui, vous pouvez le faire aussi. Utilisez EventTest.GetInvocationList() pour obtenir les méthodes enregistrées pour votre événement. Et puis utilisez -= et += pour supprimer et rajouter les délégués, respectivement. Voir l'exemple ci-dessous:

public class Test 
    { 
     public event EventHandler EventTest = delegate { }; 
     public void Method() 
     { 
      //get registered event handlers 
      Delegate[] invocationList = EventTest.GetInvocationList(); 

      //remove them 
      foreach (Delegate d in invocationList) 
      { 
       EventTest -= (EventHandler)d; 
      } 

      //this method won't trigger anything, because 
      //invocation list is empty 
      Method2(); 

      //re-add event handlers 
      foreach (Delegate d in invocationList) 
      { 
       EventTest += (EventHandler)d; 
      } 
     } 

     public void Method2() 
     { 
      if(EvenTest != null) 
      EventTest(this, EventArgs.Empty); 
     } 
    } 

J'ai enlevé le Main() trivial -method pour rendre le code plus lisible.

4

En ce qui concerne votre première question: Vous obtenez un comportement de multidiffusion par défaut. Autrement dit, si vous avez plusieurs gestionnaires, les gestionnaires d'événements seront appelés par défaut (sauf si l'un d'entre eux envoie une exception). Notez que vous pouvez modifier add (+=) et remove (-=) pour faire quelque chose de différent du comportement par défaut.

Jon Skeet a une page expliquant delegates and events in C# que vous pourriez vouloir lire.

2

Donc la réponse est oui, oui et séquentiellement dans l'ordre ajouté.

Un événement est une instance de la classe MulticastDelegate. Pour savoir quels délégués sont affectés à l'événement, appelez la méthode GetInvocationList sur l'événement. Voir http://msdn.microsoft.com/en-us/library/system.multicastdelegate.getinvocationlist%28v=VS.71%29.aspx

Cela vous donnera un tableau de délégués.Vous pouvez donc appeler GetInvocationList pour obtenir les gestionnaires d'événements existants; puis effacez les gestionnaires d'événements de l'événement; effectuer une action; puis réaffectez les gestionnaires à l'événement.

2

Les délégués sont «multicast» dans .NET et les événements sont des wrappers de type propriété. Vous pouvez obtenir une meilleure undestanding en regardant un événement en notation forme longue:

private EventHandler _handler; 

public event EventHandler MyEvent 
{ 
    add { _handler = (EventHandler)Delegate.Combine(_handler, value); } 
    remove { _handler = (EventHandler)Delegate.Remove(_handler, value); } 
} 

Vous devriez normalement écrire tous les ci-dessus en 1 ligne:

public event EventHandler MyEvent; 

Et pour être complet, un événement constitue une Invocationlist qu'il traite séquentiellement lorsqu'il est déclenché. Il n'y a aucune garantie sur la commande.

2

Et juste pour couvrir un peu, je ne pense pas que quiconque traitait avec explictly, les événements ne sont pas tous le feu en même temps - ils se déclenchent en séquence ...

Questions connexes