2016-07-26 11 views
0

Ich habe eine einfache abstrakte Klasse:Invoke Base Event-Handler in C# 6

abstract class Lesson 
{ 
    public event EventHandler<SpeakEventArgs> Speak; 
    public string OpeningMessage { get; set; } 
    public string ClosingMessage { get; set; } 
    public bool completed { get; private set; } = false; 
    abstract public void Do(); 
} 

Und eine einfache Unterklasse:

class BubbleSort : Lesson 
{ 
    public override void Do() 
    { 
     base.Speak?.Invoke(this, new SpeakEventArgs { Message = OpeningMessage }); 
    } 
} 

Die Unterklasse verwendet die C# 6 Null-Konditionaloperator ?.. Dieser Code gibt dem Fehler

die Veranstaltung ‚Lesson.Speak‘ nur auf der linken Seite erscheinen kann von + = oder - = (außer wenn innerhalb des Typs ‚Lektion‘ verwendet)

Sicher als Unterklasse bin ich hier innerhalb des Typs 'Lesson'? Wie mache ich diesen Aufruf des Basisklassenereignisses innerhalb der Unterklasse?

Antwort

0

Sie können nicht ein Ereignis in jeder Klasse andere als die geltend machen, dass es in

erklärt wurde stattdessen würde ich vorschlagen, eine Schaffung erhöhen Methode in der Basisklasse, die die erforderlichen Kontrollen dann stellt sich die Veranstaltung für Sie von do

protected void raiseSpeak(SpeakEventArgs args) 
{ 
    this.Speak?.Invoke(sender, args); 
} 

oder in Ihrem Fall die abstrakte einfach entfernen führt und heben Sie das Ereignis in der do-Methode in Ihrer Lektion Klasse, die Sie dann für zusätzliche Funktionen außer Kraft setzen

abstract class Lesson 
{ 
    public event EventHandler<SpeakEventArgs> Speak; 

    public virtual void Do() 
    { 
     this.Speak?.Invoke(sender, args); 
    } 
} 

class BubbleSort : Lesson 
{ 
    public override void Do() 
    { 
     base.Do(); 
     //do something BubbleSort related 
    } 
} 
1

Sie kann nicht direkt aufrufen ein Ereignis von außerhalb der Klasse, die es definiert, auch aus einer Unterklasse.

Lösung: Verwenden Sie eine protected Methode es Feuer:

internal abstract class Lesson 
{ 
    public event EventHandler<SpeakEventArgs> Speak; 

    public string OpeningMessage { get; set; } 
    public string ClosingMessage { get; set; } 
    public bool completed { get; private set; } = false; 

    abstract public void Do(); 

    protected void DoSpeak(SpeakEventArgs e) 
    { 
     if (this.Speak != null) 
     { 
      this.Speak(this, e); 
     } 
    } 
} 

internal class BubbleSort : Lesson 
{ 
    public override void Do() 
    { 
     base.DoSpeak(new SpeakEventArgs { Message = OpeningMessage }); 
    } 
} 
+0

'this.Speak (this, e);' ist nicht Thread-sicher, ist es möglich, etwas aus dem Ereignis zwischen dem Null-Check und dem Aufruf abzubestellen, stattdessen sollten Sie die Handler auf ein Objekt kopieren, dann überprüfen das für Null und Anruf von dort – MikeT

+1

@MKeT, die Sie absolut nichts bekommt; Du änderst einfach die Wettlaufsituation, ohne sie zu entfernen. Jetzt haben Sie ein Ereignis ausgelöst, wenn es nicht sein sollte. – InBetween

+1

@MikeT Ja, es ist nicht Thread sicher, aber es gibt nicht vor zu sein. Was Sie vorschlagen, ist auch nicht. Es ist tatsächlich ein häufiger Fehler, du solltest das nicht tun. Siehe http://blog.stephencleary.com/2009/06/threadsafe-events.html – ken2k

0

You will have to provide a raise method in your abstract class, zB:

abstract class Lesson 
{ 
    public event EventHandler<SpeakEventArgs> Speak; 
    public string OpeningMessage { get; set; } 
    public string ClosingMessage { get; set; } 
    public bool completed { get; private set; } = false; 
    abstract public void Do(); 

    protected virtual void RaiseSpeak(object sender, SpeakEventArgs args) 
    { 
     this.Speak?.Invoke(sender, args); 
    } 
} 

die Sie dann gegebenenfalls außer Kraft setzen können, zum Beispiel: