C# のデリゲートで匿名メソッドを利用する方法

C# の匿名メソッドをデリゲートで利用する

C# の匿名メソッドをデリゲートと使用することで、より簡潔にコードを記述できます。

次のサンプルコードでは 二箇所で匿名メソッドを利用しています。

ひとつ目は18行目です。デリゲートを初期化するために空の匿名メソッドを利用しています。この点については、次の節で説明します。

二つ目は37から40行目のイベントハンドラ設定箇所です。ここではイベントハンドラを匿名メソッドを利用してセットしています。

using System;
using static System.Console;

class MyArgs
{
  public int x { get; set; }
  public int y { get; set; }

  public MyArgs(int x, int y)
  {
    this.x = x;
    this.y = y;
  }
}

class MyButton
{
  public event Action ClickHandler = delegate { };

  public void Click()
  {
    // ダミーデータ
    var r = new Random();
    var x = r.Next(100);
    var y = r.Next(100);

    var args = new MyArgs(x, y);
    ClickHandler(args);
  }
}

class Program
{
  static void Main(string[] args)
  {
    var button = new MyButton();
    button.ClickHandler += delegate (MyArgs args)
    {
      WriteLine($"OnClick: ({args.x}, {args.y})");
    };
    button.Click();
  }
}

37行目から40行目の箇所は、匿名メソッドを用いる代わりにラムダ式を用いても同様のことが実現できます。

    button.ClickHandler += args =>
    {
      WriteLine($"OnClick: ({args.x}, {args.y})");
    };

デリゲート型に付いている event キーワードの意味については「C# のイベント」をご覧ください。 event キーワードによって変わる箇所もありますが、基本的にはイベントもデリゲートのひとつなので動作は同様です。

空の匿名メソッドでデリゲートを初期化する

匿名メソッドでは引数リスト及び関数本体も省略できます。 引数リストとメソッド本体を省略する場合 delegate { } と書きます。(空白は任意)

こうした空の匿名メソッドには便利な使い途があります。

デリゲートの実装では、通常実行時にデリゲートがセットされているかどうかチェックするために、 呼び出し前に null のチェックをします。もし null に対して呼び出しを試みれば null 参照例外 (System.NullReferenceException) が発生するからです。

しかし、あらかじめデリゲートを空の匿名メソッドで初期化しておくことで、null チェックをしなくても安全に呼び出すことができます。

このため、上記のサンプルコードの18行目では次のように delegate { } でデリゲートを初期化し、 28行目で利用するときには null チェックを実施していません。

public event Action<MyArgs> ClickHandler = delegate { };

尚、前述のイベントハンドラの設定ではラムダ式で同様のことが実現できましたが、ラムダ式では空の匿名メソッドと同様のことはできません。

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

© 2024 C# 入門