C#のデリゲートを手軽にする匿名メソッド

C#にはデリゲートという関数変数のように扱う仕組みがあります。

 

変数のように扱えれば、関数の引数に関数を渡す事ができます。

引数に関数が渡せれば、計算式の一部だけを簡単に差し替える事ができます。

 

※デリゲートを更に詳しく知るにはC#のデリゲート (delegate) って何?をご覧ください

 

 

汎用的なコードが作りやすいデレゲートですが、それを更に使いやすくしてくれるのが匿名メソッドです。


デリゲート(delegate)のおさらい

delegateを使ってコールバックをするサンプルを作ってみました。

以下の例は、List<int>を継承したクラスを作り、条件に合う項目だけを抜き出すWhereメソッドを作っています。この「条件に合う」という部分にdelegateを使って外に出す事で、様々な条件に対応できる汎用的なメソッドになります。

    public delegate bool TestDelegate(int obj);

    public class TestList : List<int>
    {
        public TestList Where(TestDelegate func)
        {
            var list = new TestList();
            foreach (var obj in this)
            {
                if (func(obj))
                {
                    list.Add(obj);
                }
            }
            return list;
        }
    }

以下はこのクラスを使う時のサンプルです。

    public partial class TestWindow : Window
    {
        public TestWindow()
        {
            InitializeComponent();

            var list = new TestList();
            list.Add(0);
            list.Add(1);
            list.Add(2);

            var result = list.Where(TestFunc);
        }

        public bool TestFunc(int n)
        {
            if (0 < n)
                return true;
            else
                return false;
        }
    }

15~21行目で、定義した delegate の形のメソッドを作っています。

抽出条件はアプリケーション毎に色々なケースが考えられますが、その条件の部分だけを作るだけで抽出する部分のクラスやメソッドは汎用的になります。

デリゲートの煩わしさと問題点

上記の15~21行目にあたる部分ですが、コールバックされるメソッドを作る必要があります。

作ったメソッドが何度も使われるならいいですが、たった1度の為にわざわざ別のメソッドで作るのは煩わしいと感じます。何より、コールバックの部分だけ遠く離れたところにコードを書くことになるととても分かりづらいソースコードになってしまいます。


メソッドの中にメソッドを作るのが匿名メソッド

一番の問題はコールバック部分のコードが離れたところに書かれて分かりづらいという点です。

ならば、その場所に書いちゃおうというのが匿名メソッドです。

 

上記の例を匿名メソッドに変えてみると↓このようになります。

    public partial class TestWindow : Window
    {
        public TestWindow()
        {
            InitializeComponent();

            var list = new TestList();
            list.Add(0);
            list.Add(1);
            list.Add(2);

            var result = list.Where(
                delegate(int n)
                {
                    if (0 < n)
                        return true;
                    else
                        return false;
                });
        }
    }

12行目の、引数としてメソッド名を指定していた部分に直接メソッドを書き込んでいます。

メソッドの中にメソッドがある状態です。

 

メソッド名の代わりに、それがデレゲートだと分かるよう delegate と記述します。

1度きりしか使わないので、もはやメソッド名を付ける必要はありません。

名前が無いので匿名メソッドと呼ばれるわけです。


そしてラムダ式へ

これで少しデリゲートが使いやすくなりました。

ですが、削れる部分は削ってもっと簡素に記述したいと思うかもしれません。

 

それをやる仕組みがラムダ式です。

=>】という記号を使い、書く必要のないコードを可能な限り減らします。

 

 

※ラムダ式を更に詳しく知るにはC#のラムダ式【=>】って何?をご覧ください

 

 

 

関連記事