2009-04-16 9 views
124

j'ai une classe de base qui contient les événements suivants:C#: Raising un événement hérité

public event EventHandler Loading; 
public event EventHandler Finished; 

Dans une classe qui hérite de cette classe de base que je tente de soulever l'événement:

this.Loading(this, new EventHandler()); // All we care about is which object is loading. 

Je reçois l'erreur suivante:

l'événement « BaseClass.Loading » ne peut apparaître sur le côté gauche de + = ou - = (BaseClass')

Je suppose que je ne peux pas accéder à ces événements les mêmes que d'autres membres hérités?

Répondre

138

Qu'est-ce que vous avez à faire, est la suivante:

Dans votre classe de base (où vous avez déclaré les événements), créer méthodes protégées qui peuvent être utilisées pour déclencher les événements:

public class MyClass 
{ 
    public event EventHandler Loading; 
    public event EventHandler Finished; 

    protected virtual void OnLoading(EventArgs e) 
    { 
     EventHandler handler = Loading; 
     if(handler != null) 
     { 
      handler(this, e); 
     } 
    } 

    protected virtual void OnFinished(EventArgs e) 
    { 
     EventHandler handler = Finished; 
     if(handler != null) 
     { 
      handler(this, e); 
     } 
    } 
} 

(Notez que vous devriez probablement changer ces meth ods, afin de vérifier si vous devez appeler l'eventhandler ou non).

Ensuite, dans les classes qui héritent de cette classe de base, vous pouvez simplement appeler les méthodes OnFinished ou surChargement pour élever les événements:

public AnotherClass : MyClass 
{ 
    public void DoSomeStuff() 
    { 
     ... 
     OnLoading(EventArgs.Empty); 
     ... 
     OnFinished(EventArgs.Empty); 
    } 
} 
+5

Ces méthodes doivent être protégées virtuel moins qu'il y ait une raison de faire autrement. –

+6

Pourquoi devrait-il être virtuel? Je le déclarerais virtuel si je voulais que les héritiers changent la façon dont l'événement devrait être soulevé, mais la plupart du temps, je ne vois aucune raison de le faire ... –

+0

Selon les directives Microsoft dit qu'il devrait être virtuel afin que les héritiers puissent contrôler le event .. En outre, la méthode On protected devrait prendre des arguments d'événement, pas les créer eux-mêmes. Cette réponse est fausse par rapport à la bonne par Adam Robinson. – meandmycode

7

I am assuming I cannot access these events the same as other inherited members?

Précisément. Il est habituel de fournir une fonction protégée OnXyz ou RaiseXyz pour chaque événement de la classe de base afin de permettre l'augmentation des classes héritées. Par exemple:

public event EventHandler Loading; 

protected virtual void OnLoading() { 
    EventHandler handler = Loading; 
    if (handler != null) 
     handler(this, EventArgs.Empty); 
} 

Appelé dans la classe héritée:

OnLoading(); 
111

Vous ne pouvez accéder à un événement dans la classe déclarant, comme .NET crée des variables d'instance privées derrière les scènes qui contiennent réellement le délégué. En faisant cela ..

public event EventHandler MyPropertyChanged; 

est en train de faire cela;

private EventHandler myPropertyChangedDelegate; 

public event EventHandler MyPropertyChanged 
{ 
    add { myPropertyChangedDelegate += value; } 
    remove { myPropertyChangedDelegate -= value; } 
} 

et le faire ...

MyPropertyChanged(this, EventArgs.Empty); 

est en fait ce ...

myPropertyChangedDelegate(this, EventArgs.Empty); 

Vous pouvez donc (évidemment) accéder uniquement à la variable d'instance de délégué privé à l'intérieur du déclarant classe.

La convention est de fournir quelque chose comme ça dans la classe déclarant ..

protected virtual void OnMyPropertyChanged(EventArgs e) 
{ 
    EventHandler invoker = MyPropertyChanged; 

    if(invoker != null) invoker(this, e); 
} 

Vous pouvez ensuite appeler OnMyPropertyChanged(EventArgs.Empty) de partout dans cette classe ou au-dessous de l'héritage hiérarchisé pour invoquer l'événement.

+0

J'ai eu quelques problèmes de mise en œuvre de cette ... http://stackoverflow.com/q/10593632/328397 – LamonteCristo

-1

Vous pouvez essayer cette façon, ça marche pour moi:

public delegate void MyEventHaldler(object sender, EventArgs e); 

public class B 
{ 
    public virtual event MyEventHaldler MyEvent; 
    protected override void OnChanged(EventArgs e) 
    { 
     if (MyEvent != null) 
      MyEvent(this, e); 
    } 
} 

public class D : B 
{ 
    public override event MyEventHaldler MyEvent; 
    protected override void OnChanged(EventArgs e) 
    { 
     if (MyEvent != null) 
      MyEvent(this, e); 
    } 
} 
+2

Notez que cet article met en garde contre déclarer des événements virtuels et les remplacer en déclarant que le compilateur ne gère pas cela correctement: https://msdn.microsoft.com/fr-fr/library/hy3sefw3.aspx –

Questions connexes