2016-07-26 39 views
0

我有一個簡單的抽象類:調用基地的事件處理程序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(); 
} 

和一個簡單的子類:

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

子類使用C#6空條件運算符?.。此代碼給出了錯誤

事件「Lesson.Speak」只能出現在左手側+ =或 - =

肯定(類型「課」內使用時除外)作爲一個小班我在這裏的類型'教訓'?我如何在子類中調用基類事件?

回答

0

你不能比它在

聲明相反,我建議建立一個一個以外的任何類中調用事件募集方法在執行必要的檢查,然後你的基類引發該事件對你

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

或在你的情況只是刪除從做抽象並提高在做方法的事件在課程類,然後你就可以忽略了額外的功能

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

不能直接從定義它的類外部調用一個事件,即使是從一個子類。

解決方案:使用protected方法來火了:

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);'不是線程安全的,它有可能取消訂閱null檢查和調用之間的事件,而應該將處理程序複製到對象,然後檢查對於null和來自那裏的電話 – MikeT

+1

@MIkeT讓你絕對沒有任何東西;你只是改變比賽條件,而不是將其移除。現在你有一個事件發生時,它不應該。 – InBetween

+1

@MikeT是的,它不是線程安全的,但它並不假裝。你的建議不是。這實際上是一個常見的錯誤,你不應該那樣做。見http://blog.stephencleary.com/2009/06/threadsafe-events.html – ken2k

0

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

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); 
    } 
} 

你那麼可以選擇覆蓋,如:

class BubbleSort : Lesson 
{ 
    protected override void RaiseSpeak(object sender, SpeakEventArgs args) 
    { 
     // your logic here 

     base.RaiseSpeak(sender, args); 
    } 

    public override void Do() 
    { 
     this.RaiseSpeak(this, new SpeakEventArgs() { Message = OpeningMessage }); 
    } 
}