Pourquoi les événements en C # doivent-ils prendre (expéditeur, EventArgs)?

Il est de (object sender, EventArgs args) que vous devez déclarer des événements prenant pour parameters (object sender, EventArgs args) . Pourquoi?

Cela permet au développeur consommateur d’écrire un seul gestionnaire d’événements pour plusieurs événements, indépendamment de l’expéditeur ou de l’événement.

Edit: Pourquoi auriez-vous besoin d’un modèle différent? Vous pouvez hériter de EventArgs pour fournir toute quantité de données, et la modification du modèle ne servira qu’à semer la confusion et à frustrer tout développeur qui est obligé de consumr ce nouveau modèle.

En fait, on peut se demander si c’est la meilleure façon de faire des événements. Il existe une école de pensée qui dit que les événements sont destinés à découpler deux segments de code, le fait que le gestionnaire d’événements obtienne l’expéditeur et doit savoir dans quel type l’expéditeur doit être converti pour pouvoir faire quoi que ce soit est anti- modèle.

Parce que c’est un bon modèle pour tout mécanisme de rappel, quelle que soit la langue. Vous voulez savoir qui a envoyé l’événement (l’expéditeur) et les données pertinentes pour l’événement (EventArgs).

L’utilisation d’un seul paramètre, EventArgs, pour les données transmises par un événement vous permet d’append des données à votre événement dans les versions futures de votre logiciel sans détruire les consommateurs existants. Vous ajoutez simplement de nouveaux membres à une classe dérivée de EventArgs existante ou créez une classe dérivée avec les nouveaux membres.

Sinon, la cohérence et le principe de la moindre surprise justifient l’utilisation de EventArgs pour la transmission de données.

En ce qui concerne l’expéditeur, dans certains cas (mais pas tous), il est utile de savoir quel type a envoyé l’événement. L’utilisation d’un type autre que object pour l’argument d’expéditeur est trop ressortingctive: cela signifierait que d’autres expéditeurs ne pourraient pas réutiliser la même signature d’événement.

C’est un bon modèle à utiliser, ainsi, tout ce qui implémentera l’événement pourra trouver ce qui l’envoyait.

La meilleure méthode consiste également à remplacer les EventArgs et à leur transmettre des données. Les EventArgs sont une classe de base. Si vous examinez divers contrôles qui appellent des événements, ils ont remplacé EventArgs, ce qui vous donne plus d’informations sur l’événement.

Même si vous n’avez pas besoin des arguments pour faire l’événement, si vous ne les incluez pas dans la première exécution du framework et souhaitez les append plus tard, vous annulez toutes les implémentations précédentes et devez les réécrire. De plus, si vous créez un cadre et que vous allez le dissortingbuer, les choses empireront, car toutes les personnes qui utilisent votre cadre devront procéder à une refactorisation.

Chris Anderson dit dans le livre Framework Design Guidelines:

C’est à peu près un motif. En plaçant les arguments d’événement dans une classe, vous obtenez une meilleure sémantique de gestion des versions. En ayant un modèle commun (sender, e) il est facile à apprendre comme signature pour tous les événements.

Il existe des situations impliquant principalement l’interopérabilité qui nécessiteraient une déviation de ce modèle.

Il semblait que ce fût la manière dont Microsoft a fait évoluer le modèle d’événement avec le temps. Il semble également qu’ils permettent également une autre façon de procéder avec le “nouveau” délégué d’Action et ses variantes.

“Object sender” permet de réutiliser une méthode pour plusieurs objects lorsque la méthode du gestionnaire est supposée faire quelque chose avec l’object qui a déclenché l’événement. Par exemple, 3 textbox peut avoir un seul gestionnaire qui réinitialisera le texte de la zone de texte déclenchée.

Le principal avantage de EventArgs est qu’il permet de refactoriser les informations d’événement sans avoir à modifier les signatures de tous les gestionnaires de tous les projets abonnés à ce type d’événement.

Je ne peux pas penser à une façon plus intelligente de gérer les événements.

Parfois, vous souhaitez forcer tous vos consommateurs d’événements à utiliser un paramètre d’événement particulier, par exemple un événement de sécurité qui transmet un paramètre booléen, vrai pour bon, faux pour mauvais. Dans ce cas, vous voulez que votre consommateur soit douloureusement conscient du nouveau paramètre, c’est-à-dire que vous voulez que vos consommateurs soient couplés à ce paramètre. Notez que vos consommateurs sont toujours découplés de votre classe de tir, mais pas de votre événement.

Je pense que ce scénario s’applique à un grand nombre de cas et que, dans ces cas, la valeur de EventArgs est considérablement réduite.

La classe EventArgs seule est inutile car elle doit être dérivée pour être instanciée avec n’importe quel contenu. Cela indiquerait qu’une sous-classe devrait être utilisée et qu’il en existe déjà beaucoup dans .NET. Malheureusement, je ne trouve pas de bons génériques.

Supposons que vous souhaitiez déléguer la journalisation à un événement générique … SANS ÉCRIRE VOTRE PROPRE SOUS-CLASSE EventArgs. Cela peut sembler un exercice inutile, mais j’aime bien utiliser les fonctionnalités existantes. Vous pouvez passer votre chaîne à travers l’argument Object, mais cela va à l’encontre de l’utilisation prévue. Essayez de trouver une bonne référence des sous-classes EventArgs sur Google et vous arriverez à sec. (Au moins je l’ai fait.)

ReSharper aide un peu, car lorsque vous tapez “EventArgs”, vous voyez une liste de toutes les classes (dans votre étendue using / imports) qui CONTIENNENT la chaîne “EventArgs”. En parcourant la liste, vous verrez de nombreuses classes sans membre de chaîne. Lorsque vous accédez à ControlEventArgs , vous voyez que la propriété Text peut être utilisée, mais avec tout le surmenage d’un contrôle windows. ConvertEventArgs peut être utile, car vous transmettez le type avec les données, mais cela nécessite tout de même un couplage étroit qui n’est ni bien documenté ni insortingnsèquement sûr. DataReceivedEventArgs n’a pas d’implémentation. EntryWrittenEventArgs nécessite un EventLogEntry avec un tableau d’octets ou StreamingContext pour les données. ErrorEventArgs est plus proche, avec un message Exception, si cela ne vous dérange pas d’appeler tous vos événements de journal Exception ErrorEvents en interne. FileSystemEventArgs est probablement le plus proche à l’heure actuelle, avec deux chaînes et un argument d’énumération WatcherChangeTypes requirejs qui PEUT être mis à 0, si vous savez ce que vous faites. LabelEditEventArgs utilise un int et une chaîne, si cela ne vous dérange pas de requérir l’espace de noms Windows.Forms. RenamedEventArgs est similaire à FileSystemEventArgs avec une chaîne supplémentaire. Enfin, ResolveEventArgs dans System.Runtime.InteropServices passe une seule chaîne. Il existe d’autres bibliothèques, mais je suis resté fidèle à certaines des plus courantes. Donc, selon l’implémentation, je peux utiliser ErrorEventArgs , FileSystemEventArgs ou ResolveEventArgs pour la journalisation.