Si je m'inscris à un événement en c # pendant l'envoi, suis-je assuré de ne pas être rappelé pendant cet envoi?

StackOverflow https://stackoverflow.com/questions/141423

  •  02-07-2019
  •  | 
  •  

Question

En C #, je souhaite parfois enregistrer une méthode pour un événement au milieu d'une dépêche de ce même événement. Par exemple, si j'ai une classe qui transite des états en fonction de dépêches successives du même événement, je souhaiterais peut-être que le gestionnaire du premier État se désenregistre lui-même et enregistre le deuxième. Cependant, je ne souhaite pas que le second gestionnaire soit envoyé avant le prochain déclenchement de l'événement.

La bonne nouvelle est qu’il semble que la mise en oeuvre de C # par Microsoft se comporte exactement de la même manière. Le sucre de syntaxe d'enregistrement d'événement est remplacé par un appel à System.Delegate.Combine, qui concatène simplement la liste d'appels en cours et la nouvelle méthode dans une liste séparée et l'affecte à la propriété event. Cela me donne exactement le comportement que je veux.

Ma question est donc la suivante: ce comportement est-il garanti par la norme de langue? J'aime pouvoir exécuter mon code C # sur d'autres plates-formes en mono et je veux généralement m'assurer que je ne fais pas de suppositions sur la norme de langage en fonction de son implémentation.

Je n'ai trouvé aucune information définitive sur MSDN.

Si vous souhaitez un exemple spécifique de ce dont je parle, voici un exemple:

    delegate void TestDelegate();
    static event TestDelegate TestEvent;

    static void Main (string[] args) {
        TestEvent += TestDelegateInstanceFirst;
        TestEvent();
        TestEvent();
    }

    static void TestDelegateInstanceFirst () {
        Console.WriteLine("First");
        TestEvent += TestDelegateInstanceSecond;
    }

    static void TestDelegateInstanceSecond () {
        Console.WriteLine("Second");
    }

Au moins sous Windows, le résultat est:

First
First
Second
Était-ce utile?

La solution

Oui, c'est garanti.

Dans la spécification C # 3.0 unifiée, section 15.1:

  

Cependant, lorsque deux délégués non null   les cas sont combinés, leur   Les listes d'invocation sont concaténées & # 8212; dans   l'ordre a quitté l'opérande puis à droite   opérande & # 8212; pour former une nouvelle liste d’invocation,   qui contient deux ou plusieurs entrées.

Notez la "nouvelle liste d'appels". Et encore dans la section 15.3:

  

Une fois instancié, déléguez des instances   toujours faire référence au même objet cible   et méthode. Rappelez-vous, quand deux   les délégués sont combinés, ou on est   retiré d'un autre, un nouveau délégué   résultats avec sa propre liste d'invocation;   les listes d'invocation des délégués   combinés ou supprimés restent inchangés.

Enfin, MSDN pour System.Delegate indique:

  

Les délégués sont immuables. une fois créé,   la liste d'invocation d'un délégué ne   pas changer.

Je pense qu'il y a quelque chose dans les spécifications de la CLI - je vais vérifier si vous le souhaitez, mais j'espère que ces trois-là vous ont donné suffisamment confiance:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top