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 という名前のデリゲート型を、ジェネリック型パラメータを用いて定義しています。そして、デリゲートの変数 ClickHandlerMyClickEventArgs 型を指定して宣言しています。

このデリゲートを使う側は次のように書き直せます。

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;

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 C# 入門