La compréhension des événements et des gestionnaires d'événements en C#
Je comprends le but de manifestations, en particulier dans le contexte de la création d'interfaces utilisateur. Je pense que c'est le prototype de la création d'un événement:
public void EventName(object sender, EventArgs e);
Ce faire, les gestionnaires d'événements, pourquoi sont-ils nécessaires, et comment faire pour en créer un?
- Comme le fait remarquer @Andy, l'extrait de code ici décrit la méthode inscrits à l'événement, et non l'événement lui-même.
- codeproject.com/Articles/4773/Events-and-Delegates-simplified
- Double Possible de Différence entre les événements et les délégués et ses applications
Vous devez vous connecter pour publier un commentaire.
De comprendre les gestionnaires d'événements, vous devez comprendre les délégués. Dans C#, vous pouvez penser à un délégué comme un pointeur (ou une référence) à une méthode. Ceci est utile parce que le pointeur peut être adopté comme une valeur.
Le concept central d'un délégué est sa signature, ou de la forme. C'est (1) le type de retour et (2) les arguments d'entrée. Par exemple, si nous créons un délégué
void MyDelegate(object sender, EventArgs e)
, il ne peut point des méthodes qui renvoient desvoid
, et de prendre uneobject
etEventArgs
. Un peu comme un trou carré et une cheville carrée. Donc nous disons que ces méthodes ont la même signature, ou de la forme, en tant que délégué.Donc savoir comment faire pour créer une référence à une méthode, nous allons réfléchir à la finalité des événements: nous voulons provoquer un peu de code à exécuter lorsque quelque chose se passe ailleurs dans le système - ou "gérer l'événement". Pour ce faire, nous créons des méthodes spécifiques pour le code que nous voulons être exécuté. La colle entre les événements et les méthodes à exécuter sont les délégués. L'événement doit en interne stocker une "liste" de pointeurs vers les méthodes à appeler lorsque l'événement est déclenché.* Bien sûr, pour être en mesure d'appeler une méthode, nous avons besoin de savoir quels sont les arguments à passer! Nous utilisons le délégué, le "contrat" entre l'événement et toutes les méthodes qui seront appelées.
Donc la valeur par défaut
EventHandler
(et beaucoup d'autres) représente un forme spécifique de la méthode (encore une fois, nulle/objet-EventArgs). Lorsque vous déclarez un événement, vous dites la forme de la méthode (Gestionnaire) que l'événement va invoquer, en spécifiant un délégué:(*C'est la clé d'événements .NET et des peelings à l'écart de la "magie" - un événement est vraiment, sous les couvertures, juste une liste des méthodes de la même "forme". La liste est stockée dans lequel l'événement de vie. Lorsque l'événement est "élevé", c'est vraiment juste "passer à travers cette liste de méthodes et d'appeler chacun, à l'aide de ces valeurs que les paramètres". Affectation d'un gestionnaire d'événements est juste une plus belle, la plus facile d'ajouter votre méthode pour cette liste de méthodes pour être appelé).
EventName(delegateArg1, delegateArg2);
est valide. Qui invoque le cas de la méthode, le type de coups de pied une chaîne, l'appel de chaque gestionnaire affecté à cet événement avec ces arguments.event
mot-clé est nécessaire. Il limite l'accès à des types qui ne sont pas propriétaires de l'événement += et -= uniquementthis.SomethingHappened(args);
. Si il n'y a pas d'abonnés si, SomethingHappened sera nulle, alors assurez-vous de vérifier la valeur null avant d'essayer de l'appeler.myObj.SomethingHappened += HandleSomethingHappened;
? Pourquoi, pourquoi pas, ou dans quelles circonstances?C# connaît deux termes,
delegate
etevent
. Commençons par la première.Délégué
Un
delegate
est une référence à une méthode. Comme vous pouvez créer une référence à une instance:Vous pouvez utiliser un délégué pour créer une référence à une méthode:
Maintenant que vous avez cette référence à une méthode, vous pouvez appeler la méthode par la référence:
Mais pourquoi le feriez-vous? Vous pouvez aussi appeler
myFactory.GetInstance()
directement. Dans ce cas, vous pouvez. Cependant, il existe de nombreux cas pour réfléchir à l'endroit où vous ne voulez pas le reste de l'application des connaissances demyFactory
ou à l'appel d'myFactory.GetInstance()
directement.Évidente est que si vous voulez être en mesure de remplacer
myFactory.GetInstance()
enmyOfflineFakeFactory.GetInstance()
à partir d'un endroit central (aka usine méthode motif).Usine méthode motif
Donc, si vous avez un
TheOtherClass
classe et qu'elle doit utiliser lemyFactory.GetInstance()
, c'est la façon dont le code ressemblera sans délégués (vous aurez besoin de laisserTheOtherClass
connaître le type de votremyFactory
):Si vous souhaitez utiliser les délégués, vous n'avez pas à exposer le type de mon usine:
Ainsi, vous pouvez donner un délégué de classe à utiliser, sans exposer votre type de leur. La seule chose que vous exposez est la signature de votre méthode (le nombre de paramètres que vous avez et tel).
"La Signature de ma méthode", où ai-je entendu cela avant? O oui, interfaces!!! les interfaces de décrire la signature de l'ensemble de la classe. Pensez délégués décrivant la signature d'une seule méthode!
Une autre grande différence entre une interface et d'un délégué, c'est que lorsque vous avez écrit votre classe, vous n'avez pas à dire à C# "cette méthode met en œuvre ce type de déléguer". Avec les interfaces, vous avez besoin de dire "cette classe met en œuvre ce type d'interface".
En outre, un délégué de référence (avec quelques restrictions, voir ci-dessous) référence à plusieurs méthodes (appelées
MulticastDelegate
). Cela signifie que lorsque vous appelez le délégué, plusieurs explicitement-joint méthodes seront exécutées. Une référence de l'objet peut toujours seule référence à un objet.Les restrictions pour un
MulticastDelegate
sont que le (la méthode/de l'délégué) signature ne doit pas avoir une valeur de retour (void
) et les mots-clésout
etref
n'est pas utilisé dans la signature. Évidemment, vous ne pouvez pas appeler deux méthodes qui retournent un nombre et à retourner le même nombre. Une fois que la signature est conforme, le délégué est automatiquement unMulticastDelegate
.Événement
Événements sont seulement des propriétés (comme le get;set; propriétés des champs d'instance) qui exposent abonnement à la déléguer à partir d'autres objets. Ces propriétés, cependant, ne prennent pas en charge get;set;. Au lieu de cela, ils soutiennent ajouter; supprimer;
De sorte que vous pouvez avoir:
Utilisation dans l'INTERFACE utilisateur (WinForms,WPF,UWP etc)
Donc, maintenant nous savons qu'un délégué est une référence à une méthode et que l'on peut avoir d'un événement à faire savoir au monde qu'ils peuvent nous donner leurs méthodes pour être référencé à partir de notre délégué, et nous sommes un bouton de l'INTERFACE utilisateur, puis: on peut demander à n'importe qui qui est intéressé à savoir si j'ai été cliqué, pour enregistrer leur méthode avec nous (par l'intermédiaire de l'événement, nous avons exposé). Il peut utiliser toutes les méthodes qui nous ont été donnés et de les référencer par notre délégué. Et puis, nous allons attendre et attendre.... jusqu'à ce qu'un utilisateur vient et clique sur le bouton, puis nous allons avoir assez de raison d'invoquer le délégué. Et parce que le délégué références de toutes ces méthodes donné à nous, toutes ces méthodes sera invoquée. Nous ne savons pas ce que ces méthodes font, ni nous ne savons classe qui implémente ces méthodes. Tous nous ne de soins, c'est que quelqu'un était intéressé à nous d'être cliqué, et nous a donné une référence à une méthode qui respecte nos souhaité signature.
Java
Langues comme Java n'ont pas de délégués. Ils utilisent des interfaces à la place. La façon de faire c'est de demander à quelqu'un qui est intéressé par "nous, cliqué sur", pour mettre en œuvre un certain interface (avec une certaine méthode, nous pouvons l'appeler), puis nous donner la totalité de l'instance qui implémente l'interface. Nous maintenons une liste de tous les objets implémentant cette interface et peut appeler leur "méthode certain que nous pouvons appeler" dès qu'on a cliqué.
event
est simple syntaxe de sucre, rien de plus.Voici un exemple de code qui peuvent vous aider:
OnMaximum?.Invoke(this,new MyEventArgs("you've entered..."));
Qui est en fait la déclaration pour un gestionnaire d'événement - une méthode qui sera appelée lorsqu'un événement est déclenché. Pour créer un événement, vous devez écrire quelque chose comme ceci:
Et puis vous pouvez vous inscrire à l'événement comme ceci:
Avec OnMyEvent() définie comme ceci:
Chaque fois que
Foo
déclencheMyEvent
, alors votreOnMyEvent
gestionnaire sera appelé.Vous n'avez pas toujours à utiliser une instance de
EventArgs
comme second paramètre. Si vous souhaitez inclure des informations supplémentaires, vous pouvez utiliser une classe dérivée deEventArgs
(EventArgs
est la base d'une convention). Par exemple, si vous regardez certains des événements définis surControl
en WinForms, ouFrameworkElement
dans WPF, vous pouvez voir des exemples d'événements qui passent de l'information supplémentaire pour les gestionnaires d'événements.OnXXX
modèle de nommage pour votre gestionnaire d'événement. (Bêtement, OnXXX est-à-dire une "poignée XXX" dans MFC, et relancer XXX " dans .net, et donc son sens est obscur et déroutant - voir ce post pour plus de détails ). Noms préférés seraitRaiseXXX
pour déclencher des événements, etHandleXXX
ouSender_XXX
à pour les gestionnaires d'événements.Juste pour ajouter à l'existant de grandes réponses ici - en s'appuyant sur le code de la accepté de, qui utilise un
delegate void MyEventHandler(string foo)
...Parce que le compilateur connaît le type de délégué de la SomethingHappened événement, ce:
Est totalement équivalent à:
Et les gestionnaires peuvent également être non avec
-=
comme ceci:À des fins d'exhaustivité, de sensibilisation de l'événement peut être fait comme ceci, uniquement dans la classe qui est propriétaire de l'événement:
Le fil-d'une copie locale du gestionnaire est nécessaire pour s'assurer que l'invocation est thread-safe, sinon un thread pourrait aller et annuler l'inscription de la dernière gestionnaire pour l'événement immédiatement après, nous avons vérifié si c'était
null
, et nous aurions un "plaisir"NullReferenceException
là.C# 6 a introduit un joli court de la main pour ce modèle. Il utilise le nul de la propagation de l'opérateur.
Ma compréhension des événements est;
Délégué:
Une variable pour contenir la référence à la méthode ou des méthodes pour être exécuté. Cela rend-il possible de passer autour des méthodes comme une variable.
Étapes de la création et de l'appel de l'événement:
L'événement est une instance d'un délégué
Depuis un événement est une occurrence d'un délégué, alors nous devons d'abord définir le délégué.
Attribuer la méthode ou les méthodes à exécuter lorsque l'événement est déclenché (Appelant le délégué)
Feu de l'événement (Appeler le délégué de)
Exemple:
editeur: où les événements se produisent. Éditeur doit spécifier le délégué de la classe et de générer des arguments nécessaires, passer ces arguments et lui-même pour le délégué.
abonné: lorsque la réponse arrive. L'abonné doit préciser les méthodes à réagir à des événements. Ces méthodes devraient prendre le même type d'arguments que le délégué. Abonné ajoutez ensuite cette méthode à l'éditeur délégué.
Par conséquent, lorsque l'événement se produire dans l'éditeur, délégué recevra certains arguments d'événement (données, etc), mais l'éditeur n'a aucune idée de ce qui va arriver avec toutes ces données. Les abonnés peuvent créer des méthodes dans leur propre classe pour répondre à des événements dans l'éditeur de la classe, afin que les abonnés puissent répondre à l'éditeur d'événements.
Je suis d'accord avec KE50 sauf que j'ai vue de l '"événement" mot-clé comme un alias pour "ActionCollection' depuis l'événement dispose d'un ensemble d'actions à effectuer (ie. le délégué).
La grande qualité technique des réponses dans le post! Je n'ai rien techniquement d'ajouter que.
L'une des principales raisons pour lesquelles de nouvelles fonctionnalités apparaissent dans des langues et des logiciels en général est du marketing ou de la politique de compagnie! 🙂 Il ne doit pas être sous-estimée!
Je pense que cela s'applique à étendre certaines des délégués et des événements trop! je les trouve utiles et ajouter de la valeur pour le langage C#, mais d'un autre côté, le langage Java a décidé de ne pas les utiliser! ils ont décidé que ce que vous avez à résoudre avec les délégués, vous pouvez déjà résoudre avec les éléments existants de la langue, c'est à dire des interfaces par exemple
Maintenant aux alentours de 2001, Microsoft a sorti .NET framework et le langage C# comme un concurrent, solution de Java, de sorte qu'il était bon d'avoir des NOUVELLES FONCTIONNALITÉS que Java n'a pas.
J'ai récemment fait un exemple de comment utiliser les événements en c#, et posté sur mon blog. J'ai essayé de la rendre aussi claire que possible, avec un exemple très simple. Dans le cas où ça pourrait aider quelqu'un, c'est ici: http://www.konsfik.com/using-events-in-csharp/
Il comprend la description et le code source (avec beaucoup de commentaires), et il se concentre principalement sur une bonne (template) de l'utilisation des événements et des gestionnaires d'événements.
Quelques points clés sont:
Événements sont comme des "sous - types de délégués", n'est plus soumis à une contrainte (dans le bon sens). En fait, d'un événement, la déclaration comprend toujours un délégué (gestionnaires d'événements sont un type de délégué).
Les Gestionnaires d'événements sont des types spécifiques de délégués (vous pouvez y penser comme à un modèle), ce qui force l'utilisateur à créer des événements qui ont une "signature". La signature est de la forme: (object sender, EventArgs eventarguments).
Vous pouvez créer votre propre sous-classe EventArgs, afin d'inclure n'importe quel type d'informations de l'événement, il faut transmettre. Il n'est pas nécessaire d'utiliser des gestionnaires d'événements en utilisant des événements. Vous pouvez complètement les ignorer, et d'utiliser votre propre genre de déléguer à leur place.
Une des principales différences entre l'utilisation des événements et des délégués, est que les événements ne peut être invoqué à partir de l'intérieur de la classe à laquelle ils ont été déclarés en, même si elles peuvent être déclarées comme public. C'est une distinction très importante, car elle permet à vos événements à être exposé, de sorte qu'ils sont "connectés" à l'externe des méthodes, tandis que dans le même temps, ils sont protégés de l'externe "utilisation abusive".