C# のイベントの実装方法
C# での基本的なイベントの実装方法
C# におけるイベントはデリゲートを利用して実装します。
デリゲートの実装に不安がある方は「C# のデリゲート」を読むことをお勧めします。
「C# のジェネリックデリゲート」でみた基本的なデリゲートは、次のようなコードになります。
using System;
class MyButton
{
public delegate void MyEventHandler<T>(T args);
public MyEventHandler<MyEventArgs> ClickHandler;
}
これをイベントとするには、次のように event キーワードを付けるだけです。
using System;
class MyButton
{
public delegate void MyEventHandler<T>(T args);
public event MyEventHandler<MyEventArgs> ClickHandler;
}
これによって、元のデリゲートと比べて次の二つの点が変わります。
- デリゲートにイベントハンドラをセットするときに += が必要とされる
- 直接デリゲートを呼び出すことができなくなる
イベントを使うサンプルコードは次のようになります。
using System;
using static System.Console;
class MyEventArgs
{
public int x { get; set; }
public int y { get; set; }
public MyEventArgs(int x, int y)
{
this.x = x;
this.y = y;
}
}
class MyButton
{
public delegate void MyEventHandler<T>(T args);
public event MyEventHandler<MyEventArgs> ClickHandler;
public void Click()
{
// ダミーデータ
var r = new Random();
var x = r.Next(100);
var y = r.Next(100);
if (ClickHandler != null)
{
var args = new MyEventArgs(x, y);
ClickHandler(args);
}
}
}
class Program
{
static void Main(string[] args)
{
var button = new MyButton();
button.ClickHandler += OnClick;
button.Click();
}
static void OnClick(MyEventArgs args)
{
WriteLine($"OnClick: ({args.x}, {args.y})");
}
}
.NET 標準の EventHandler デリゲートを利用
.NET のクラスライブラリには、 EventHandler という名前のデリゲートがあらかじめ用意されています。
public delegate void EventHandler<TEventArgs>(object? sender, TEventArgs e);
最初のパラメータには、イベントを発行するオブジェクトを渡し、二つの目パラメータにはジェネリックタイプパラメータで指定した型の任意のデータが渡される形式です。
これを用いると上で示した例は,次のように少し簡単に書き換えられます。
using System;
using static System.Console;
class MyEventArgs
{
public int x { get; set; }
public int y { get; set; }
public MyEventArgs(int x, int y)
{
this.x = x;
this.y = y;
}
}
class MyButton
{
public event EventHandler<MyEventArgs> ClickHandler;
public void Click()
{
// ダミーデータ
var r = new Random();
var x = r.Next(100);
var y = r.Next(100);
if (ClickHandler != null)
{
var args = new MyEventArgs(x, y);
ClickHandler(this, args);
}
}
}
class Program
{
static void Main(string[] args)
{
var button = new MyButton();
button.ClickHandler += OnClick;
button.Click();
}
static void OnClick(object sender, MyEventArgs args)
{
WriteLine($"OnClick: ({args.x}, {args.y})");
}
}
ひとつ目の変更点は18行目です。デリゲートの定義をすることなく、ただちにイベントを宣言できています。
二つ目の変更点は30行目です。イベントハンドラのひとつ目のパラメータに this を渡しています。
三つ目の変更点は44行目です。イベントハンドラのひとつ目のパラメータで、イベントを発行したオブジェクトの参照を受け取れるようにしています。