C# のジェネリックデリゲート
デリゲートでジェネリック型パラメータを使う
デリゲート型の定義にジェネリック型パラメータを使うことで、より汎用的なデリゲートを作ることができます。
「C# のデリゲートの基本」で説明したサンプルコードを、ジェネリック型パラメータを使うことで、 もっと簡潔に書いてみましょう。
まず、デリゲート型の定義は次のようになります。
using System;
class MyClickEventArgs : EventArgs
{
public int x { get; set; }
public int y { get; set; }
public MyClickEventArgs(int x, int y)
{
this.x = x;
this.y = y;
}
}
class MyButton
{
public delegate void MyEventHandler<T>(T args);
public MyEventHandler<MyClickEventArgs> ClickHandler;
public void Click()
{
// Dummy Data
var r = new Random();
var x = r.Next(100);
var y = r.Next(100);
if (ClickHandler != null)
{
var args = new MyClickEventArgs(x, y);
ClickHandler(args);
}
}
}
ポイントは 17-18行目です。
ここでは MyEventHandler という名前のデリゲート型を、ジェネリック型パラメータを用いて定義しています。そして、デリゲートの変数 ClickHandler は MyClickEventArgs 型を指定して宣言しています。
このデリゲートを使う側は次のように書き直せます。
using static System.Console;
class Program
{
static void Main(string[] args)
{
var button = new MyButton();
button.ClickHandler += OnClick;
button.Click();
}
static void OnClick(MyClickEventArgs args)
{
WriteLine($"OnClick: ({args.x}, {args.y})");
}
}
OnClick 関数が受け取るパラメータが MyClickEventArgs 型となり、 EventArgs 型からキャストする必要がなくなっています。
また、同時にこのコードを拡張してデリゲートを多数作る場合にも、デリゲートの型自体は多数作ることなく、それぞれのコールバックに特化した引数を受け取るデリゲートを作ることができるようになります。
C# の Action デリゲート
.NET では Action デリゲートというビルトインのデリゲート型が用意されており、これを使うことでより簡単にデリゲートを利用することができるようになります。
Action デリゲートは戻り値がない場合に利用します。
Action デリゲートは引数を受け取らないものから、16個まで受け取るものまであらかじめ用意されています。
上記の MyButton クラスのデリゲートを定義している場所は次の箇所です。
public delegate void MyEventHandler<T>(T args);
public MyEventHandler<MyClickEventArgs> ClickHandler;
既に用意されている Action デリゲートを使えば、delegate キーワードでデリゲートを作る必要がなくなりますから、この部分は次の一行で書けるようになります。
public Action<MyClickEventArgs> ClickHandler;
C# の Func デリゲート
Func デリゲートは戻り値がある場合に使う、ビルトインデリゲートです。
Func デリゲートも 0個から16個までの引数を取るものが用意されています。
Func デリゲートでは、戻り値の型はジェネリック型パラメータリストの最後に記載します。 例えば、 int 型と string 型を受け取り、bool 型を返す Func デリゲートは次のようになります。
public Func<int, string, bool> FooHandler;