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

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

  •  01-07-2019
  •  | 
  •  

Question

Il est connu que vous devez déclarer les événements prenant comme paramètres (expéditeur d'objet, arguments Arguments EventArgs) . Pourquoi?

Était-ce utile?

La solution

Cela permet au développeur consommateur d'écrire un seul gestionnaire d'événements pour plusieurs événements, quel que soit l'expéditeur ou l'événement.

Modifier: Pourquoi auriez-vous besoin d'un modèle différent? Vous pouvez hériter de EventArgs pour fournir n’importe quelle quantité de données, et la modification du modèle ne servira pas à confondre et à frustrer tout développeur qui est contraint de consommer ce nouveau modèle.

Autres conseils

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- motif.

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 paramètre unique, EventArgs, pour les données transmises par un événement vous permet d'ajouter 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 vous 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 objet pour l'argument d'expéditeur est trop restrictive: 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 événement qui implémentera l’événement peut 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 différents contrôles qui appellent des événements, ils ont substitué EventArgs, ce qui vous donne davantage 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 ajouter plus tard, vous cassez 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 distribuer, la situation s’aggravera, car tous ceux qui utilisent votre cadre devront refactoriser.

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 (expéditeur, e) , il est facile à apprendre en tant que signature de tous les événements.

Il existe des situations impliquant principalement l'interopérabilité qui nécessiteraient un écart par rapport à ce modèle.

Il semblait que ce soit 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 le faire avec le "nouveau" Un délégué d'action et ses variations.

" Object sender " permet de réutiliser une méthode pour plusieurs objets lorsque la méthode du gestionnaire est supposée faire quelque chose avec l'objet 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 à un moyen plus intelligent 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 souhaitez que votre consommateur soit douloureusement conscient du nouveau paramètre, c’est-à-dire 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 soupçonne 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 aucun bon générique.

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 verrez 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 toujours un couplage étroit qui n'est ni bien documenté ni intrinsè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, avec deux chaînes et un argument d’énumération WatcherChangeTypes requis qui PEUT être défini sur 0, si vous savez ce que vous faites. LabelEditEventArgs utilise un int et une chaîne, si cela ne vous dérange pas de nécessiter l'espace de noms Windows.Forms. RenamedEventArgs est similaire à FileSystemEventArgs avec une chaîne supplémentaire. Enfin, ResolveEventArgs dans System.Runtime.InteropServices transmet une seule chaîne. Il existe d'autres bibliothèques, mais je m'en suis tenu à certaines des plus courantes. Par conséquent, selon l’implémentation, je peux utiliser les ErrorEventArgs , FileSystemEventArgs ou ResolveEventArgs pour la journalisation.

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