2010-11-29 4 views
1

Dire que j'ai une classe comme ceci:Quels contrôles permettent d'appeler un événement?

public class FauxIdentityForm 
{ 
    public Guid FormID { get; set; } 
    public event EventHandler Closed; 
    public void TheObjectWasClosed(EventArgs e) 
    { 
     Closed(this, e); 
    } 
} 

Il est très bien pour moi d'appeler l'événement fermé à l'intérieur de la méthode TheObjectWasClosed. Mais si, dans une autre classe (même dans le même fichier), j'ai une méthode comme ceci:

public void CallTheEvent() 
{ 
    FauxIdentityForm _formIdentity = new FauxIdentityForm {FormID = Guid.NewGuid()}; 

    _formIdentity.Closed(_formIdentity, null); // <-- Does not compile! 
} 

L'appel à Fermé est abattu par le compilateur (il veut utiliser seulement + = et - =).

Donc, est en train d'appeler l'événement uniquement autorisé dans la classe? Est-ce la limitation?

Si tel est le cas, y a-t-il autour de lui? Et sinon, pourquoi les créateurs de C# font-ils cela? (Cela rend parfois très difficile le travail avec les événements.J'imagine qu'il y a une bonne raison et cela me sauve probablement de moi-même, mais j'aimerais le savoir.)

Répondre

5

Il est compliqué :)

Qu'est-ce que vous utilisez est appelé un événement comme champ . Lorsque vous en déclarez un dans votre classe, vous créez un champ et un événement. Lorsque vous appelez l'événement, vous appelez le délégué auquel le champ renvoie. Comme il s'agit d'un champ privé, vous y avez accès au sein de la classe (et de tous les types imbriqués), mais pas à l'extérieur.

Les événements eux-mêmes dans C# seulement support ajouter et supprimer des opérations. De l'extérieur, les appelants peuvent seulement s'abonner à un événement et se désabonner. Ils ne peuvent pas le soulever, ou trouver quelque chose sur qui est abonné. Bien sûr, la classe peut fournir une méthode qui augmentera l'événement, mais l'autre classe ne peut pas accéder au champ de sauvegarde de l'événement.

J'ai écrit ceci plus en détail dans un article about events and delegates.

+0

Donc, encore un peu confus, mais laissez-moi reformuler ce que je pense que vous dites et j'espère que j'ai raison: La seule ligne 'événement public EventHandler Closed; crée deux éléments dans l'IL? Celui qui est réellement public et celui qui est privé? L'événement est public donc il peut être consulté à l'intérieur et à l'extérieur de la classe. Le champ "caché" (je ne sais pas comment l'appeler) est privé et ne peut pas être appelé sauf à l'intérieur de la classe? – Vaccano

+1

@Vaccano: Oui. Il déclare un champ et un événement. C'est un peu comme une propriété implémentée automatiquement à partir de C# 3, qui crée une propriété et un champ en une fois. Personnellement, je souhaite que la syntaxe de l'événement de type champ soit 'public event EventHandler Closed {add; retirer; } '- cela aurait été plus évident, IMO. –

1

Donc, l'appel est seulement autorisé à l'intérieur de la classe? Est-ce la limitation?

Oui

Si oui, est-il de toute façon autour d'elle?

Seulement avec le consentement (aide) de la classe FauxIdentityForm. Il pourrait avoir une méthode publique OnClosed().
Un événement ressemble beaucoup à une propriété, l'un de ses principaux objectifs est l'encapsulation et c'est ce que vous avez rencontré.

+0

Dans le monde System.Windows.Forms, il est courant d'exposer une méthode OnX() virtuelle protégée (X est le nom de l'événement) qui permet aux sous-classes de contrôler l'accès ou d'appeler directement l'événement. Vous pouvez rendre cette méthode interne si vous souhaitez l'appeler d'autres classes – cordialgerm

2

En fait, Closed(this, e); est rien mais appelant invoke sur un délégué privé. C'est pourquoi seule la classe peut l'appeler. C# cache toute la complexité de votre part et crée un délégué de type événement privé pour vous (vous pouvez utiliser ILDASM pour voir tout cela).

Ceci est privé donc c'est même pas protégé. C'est pourquoi il est recommandé d'utiliser une méthode protégée pour déclencher l'événement afin que les sous-classes puissent avoir accès à l'événement.

Questions connexes