Posted by & filed under .NET.

C# eventのオーバーライドと基底クラスで発生するイベントの処理C#のeventはvirtualが宣言できて、派生クラスでoverrideできますが、そのオーバーライドされたイベントに登録したイベントハンドラを基底クラス側から呼び出せません。これはeventは宣言された同一クラス内でのみ発生させることができると言うC#の言語仕様なので当たり前と言えば当たり前の動作なのですが、適切な処理をしていないがために基底クラス側でイベントを発生させたときにExceptionが発生してしまったりと言うことがあります。(別の言い方を知れば派生クラスから基底クラスのイベントを発生させることができません。)

まぁ頭の悪い子(俺)はそれでずっとうじうじ悩んだりするわけです。

具体的にはイベントをオーバライドしたら、そのオーバーライドしたイベントの基底クラスのイベントのイベントハンドラを用意し、そのイベントハンドラで、オーバーライドしたイベントを呼び出します。ようはイベントが伝達できるようにすればいいわけですねって、オーバーライドって文字がたくさん出てきて何かよくわかりませんね。と言うことでサンプルを以下にのせます。

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  
   6:  namespace EventTest
   7:  {
   8:      class Program
   9:      {
  10:          static void Main(string[] args) {
  11:              Test test = new Test();
  12:              test.TestEvent += new EventHandler<TestEventArgs>(test_TestEvent);
  13:              test.Fire();
  14:              test.BaseFire();
  15:              Console.Read();
  16:          }
  17:  
  18:          static void test_TestEvent(object sender, TestEventArgs e) {
  19:              Console.WriteLine(e.Message);
  20:          }
  21:      }
  22:  
  23:      //基底クラス
  24:      public class TestBase
  25:      {
  26:          //イベントをvirtualで宣言する。
  27:          internal virtual event EventHandler<TestEventArgs> TestEvent;
  28:          //イベントを発生させる
  29:          public void BaseFire() {
  30:              TestEventArgs args = new TestEventArgs("Fired on Base class");
  31:              TestEvent(this, args);//派生クラス側で処理がないとイベントを発生できないので、ここでExceptionが発生する。
  32:          }
  33:  
  34:      }
  35:  
  36:      //派生クラス
  37:      public class Test : TestBase
  38:      {
  39:          internal override event EventHandler<TestEventArgs> TestEvent;
  40:  
  41:          public Test() {
  42:              //基底クラスのイベントにイベント伝達用のイベントハンドラを登録する。
  43:              base.TestEvent += new EventHandler<TestEventArgs>(Test_TestEvent);
  44:          }
  45:          //イベント伝達用のイベントハンドラ
  46:          void Test_TestEvent(object sender, TestEventArgs e) {
  47:              //利用先に基底クラスのイベントを伝達する
  48:              this.TestEvent(sender, e);
  49:          }
  50:          //イベントを発生させる
  51:          public void Fire() {
  52:              TestEvent(this, new TestEventArgs("Fired on Extended class"));
  53:          }
  54:      }
  55:  
  56:      public class TestEventArgs : EventArgs
  57:      {
  58:          public TestEventArgs(string message) {
  59:              this.Message = message;
  60:          }
  61:          public string Message { get; set; }
  62:      }
  63:  }

実行結果

Fired on Extended class

Fired on Base class

当たり前と言えば当たり前のコードなんですがeventのvirtual / override含めて書籍やネットにあまりサンプルが無いようなので載せてみました。

Tags: