C#: événement explicitement ajouter/supprimer != typique de l'événement?
Je l'ai déclaré à un générique de gestionnaire d'événement
public delegate void EventHandler();
à laquelle j'ai ajouté de la méthode d'extension 'RaiseEvent':
public static void RaiseEvent(this EventHandler self) {
if (self != null) self.Invoke();
}
Quand j'définir l'événement en utilisant la syntaxe typique
public event EventHandler TypicalEvent;
alors je peux appeler la méthode d'extension sans problèmes:
TypicalEvent.RaiseEvent();
Mais quand je définissent l'événement explicite ajout/suppression de syntaxe
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent {
add { _explicitEvent += value; }
remove { _explicitEvent -= value; }
}
ensuite la méthode d'extension n'existe pas sur l'événement défini de manière explicite ajout/suppression de syntaxe:
ExplicitEvent.RaiseEvent(); //RaiseEvent() does not exist on the event for some reason
Et quand j'ai passez la souris sur l'événement pour voir la raison pour laquelle il dit:
L'événement "ExplicitEvent' ne peut
apparaissent sur le côté gauche de l' += ou
-=
Pourquoi un événement défini à l'aide de la syntaxe typique être différent d'un événement défini à l'aide de l'explicite ajout/suppression de syntaxe et pourquoi les méthodes d'extension ne fonctionne pas sur l'autre?
EDIT: j'ai trouvé, je peux le contourner en utilisant le gestionnaire d'événement privé directement:
_explicitEvent.RaiseEvent();
Mais je ne comprends toujours pas pourquoi je ne peux pas utiliser l'événement directement comme des cas définis à l'aide de la syntaxe typique. Peut-être que quelqu'un peut m'éclairer.
- Vous ne pouvez pas également utiliser l'extension de la méthode à partir de l'extérieur de la classe.
Vous devez vous connecter pour publier un commentaire.
Parce que vous pouvez faire cela (il est non dans le monde réel de l'échantillon, mais il ne "marche"):
Comment le compilateur sait ce qu'il doit faire avec "ExplicitEvent.RaiseEvent();"?
Réponse: Il ne peut pas.
La "ExplicitEvent.RaiseEvent();" n'est que la syntaxe de sucre, qui peut être fondé uniquement si l'événement est implicitement mis en œuvre.
Lorsque vous créez un "champ" comme événement, comme ceci:
le compilateur génère un champ et un événement. Dans le code source de la classe qui déclare l'événement, tout le temps de vous référer à
Foo
le compilateur que vous comprenez que vous faites allusion à la champ. Cependant, le domaine est privé, donc, à tout moment vous vous référez àFoo
de autres des classes, il fait référence à l'événement (et, par conséquent, l'ajout/suppression de code).Si vous déclarez votre propre explicite ajouter/supprimer le code, vous n'avez pas obtenir un auto-généré le terrain. Donc, vous avez seulement un événement, et vous ne pouvez pas déclencher un événement directement en C#, vous pouvez uniquement appeler une instance de délégué. Un événement n'est pas une instance de délégué, c'est juste un ajout/suppression de paire.
Maintenant, votre code contenait ceci:
C'est un peu différent encore, il n'était pas à la déclaration d'une événement - c'était de déclarer un public champ du type de délégué
EventHandler
. Personne peut invoquer que, parce que la valeur est une instance de délégué. Il est important de comprendre la différence entre un champ et un événement. Vous ne devriez jamais écrire ce genre de code, comme je suis sûr que vous n'avez pas l'habitude d'avoir des champs publics dans d'autres types tels questring
etint
. Malheureusement, c'est une simple faute de frappe à faire, et relativement difficile à arrêter. Vous ne l'apercevez, en remarquant que le compilateur a été vous permettant d'attribuer ou utiliser la valeur d'une autre classe.Voir mon l'article sur les événements et les délégués pour plus d'informations.
C'est parce que vous n'êtes pas regardant à droite.
La logique est la même que dans les Propriétés.
Une fois que vous avez défini l'option ajouter/supprimer, ce n'est plus un événement réel, mais un wrapper pour exposer l'événement réel (événements ne peut être déclenchée à partir de l'intérieur de la classe elle-même, si vous avez toujours accès localement à l'événement réel).
Dans les deux cas, le membre avec les get/set ou sur ajouter/supprimer des biens n'a pas vraiment d'contenir toutes les données. Vous avez besoin d'un "vrai" membre privé pour contenir les données réelles.
Les propriétés permet de programmer la logique supplémentaire lorsque l'on expose les membres à l'extérieur du monde.
Un bon exemple de POURQUOI vous voulez le faire, c'est arrêter de supplémentaires de calcul quand il n'est pas nécessaire (personne n'est à l'écoute de l'événement).
Par exemple, permet de dire que les événements sont déclenchés par un timer, et nous ne voulons pas la minuterie de travail si vous n'êtes pas inscrits à l'événement:
Vous auriez probablement souhaitez verrouiller la ajouter/supprimer un objet (un coup)...
La "plaine" déclaration pour TypicalEvent fait du compilateur de la ruse. Il crée un événement de saisie des métadonnées, d'ajouter et de supprimer des méthodes et un champ de stockage. Lorsque votre code se réfère à TypicalEvent, le compilateur traduit dans une référence à la sauvegarde de terrain; lorsque le code externe se réfère à TypicalEvent (à l'aide d' += et -=), le compilateur traduit dans une référence à l'ajouter ou de supprimer la méthode.
La "explicite" déclaration contourne ce compilateur supercherie. Vous êtes en épelant les ajouter et supprimer des méthodes et de la sauvegarde de champ: en effet, comme TcKs le souligne, il peut même ne pas être un champ de stockage (ce qui est une raison commune pour l'utilisation de la forme explicite: voir, par exemple, des événements dans le Système.De Windows.Les formulaires.De contrôle). Donc le compilateur ne peut plus tranquillement traduire la référence à TypicalEvent dans une référence à la sauvegarde de domaine: si vous souhaitez que le champ de stockage, le délégué de l'objet, vous avez pour référence le champ de stockage directement: