2009-04-16 8 views
124

次のイベントが含まれている基本クラスがあります。C#:継承されたイベントを発生させる

public event EventHandler Loading; 
public event EventHandler Finished; 

この基本クラスから継承するクラスで、イベントを発生させようとします。

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

次のエラーが表示されます。

'BaseClass.Loading'イベントは、+ =または - =(BaseClass ')の左側にのみ表示されます。

他の継承メンバーと同じイベントにアクセスできないと仮定していますか?

答えて

138

は、あなたがしなければならない何、これは次のようになります。たとえば、あなたのベースクラスで

(あなたがイベントを宣言している場合)、作成イベントを発生させるために使用できる保護されたメソッド:

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

(これらのメソッドを変更する必要がありますあなたがイベントハンドラを起動する必要があるかどうかをチェックするために、odsを使用します)。 .NETとして、あなたが唯一の宣言クラスでイベントにアクセスすることができます

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

そうでない場合は行うには、いくつかの理由がありますしない限り、これらの方法は、仮想保護する必要があります。 –

+6

なぜ仮想であるべきですか?継承者がイベントを発生させる方法を変更したいと思えば、私は仮想を宣言しますが、ほとんどの場合、これを行う理由はありません。 –

+0

ガイドラインによると、マイクロソフトは、継承者が、さらに、Onプロテクトメソッドはイベント引数を取る必要があります。この答えは、Adam Robinsonの正しい答えと比べて間違っています。 – meandmycode

7

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

正確に。継承されたクラスからの昇格を有効にするには、基本クラスの各イベントに対して保護された関数OnXyzまたはRaiseXyzを提供することが慣例です。

継承されたクラスに呼び出され
public event EventHandler Loading; 

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

OnLoading(); 
111

次に、この基本クラスから継承するクラスでは、あなただけのイベントを発生させるためにOnFinishedまたはOnLoadingメソッドを呼び出すことができますデリゲートを実際に保持するシーンの背後にプライベートインスタンス変数を作成します。これを行う..

public event EventHandler MyPropertyChanged; 

実際にこれを行っています。

private EventHandler myPropertyChangedDelegate; 

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

とこれをやって...

MyPropertyChanged(this, EventArgs.Empty); 

は実際にこれです...

myPropertyChangedDelegate(this, EventArgs.Empty); 

だから、(明らかに)のみ宣言内からプライベートデリゲートのインスタンス変数にアクセスすることができますクラス。

大会が宣言クラスでこのような何かを提供することです。..

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

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

あなたは、イベントを呼び出すためにどこにでも、そのクラス内または継承階層構造の下からOnMyPropertyChanged(EventArgs.Empty)を呼び出すことができます。

+0

私はこれを実装するいくつかの問題がありました... http://stackoverflow.com/q/10593632/328397 – LamonteCristo

-1

あなたはそれが私のために動作しますが、この方法を試すことができます。

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

この記事は仮想イベントを宣言し、コンパイラがこれを正しく処理しないと主張するようにオーバーライドします。https://msdn.microsoft.com/en-us/library/hy3sefw3.aspx –

関連する問題