C# ゼロから理解するラムダ式:戻り値を持つ匿名メソッドを書く方法 #8

通常の匿名メソッドについては前回の「C# ゼロから理解するラムダ式:匿名メソッド(無名関数)を書く方法 #7」で紹介しているので、こちらの続きになります。今回は匿名メソッドが戻り値を持つ場合にどう記述するかを解説していきます。

戻り値を持つ場合でも、これまでと同様な方法でデリゲートを記述できますが、明確に違うのは処理の中で戻りを記述する必要があるということです。また、通常はメソッドのシグネチャで戻り値を記述する必要がありますが、デリゲートの宣言部分で記述しておけば十分になります。

戻り値を持つ匿名メソッドの書き方

新規のコンソールアプリケーションを作成して、以下のサンプルコードを書いてみてください。今回もusingの削除と並べ替えを行っているので、初期状態とはusingの部分が少し異なっているかと思います。

using System;
using System.Collections.Generic;

namespace App05
{
    class Program
    {
        //デリゲート
        delegate bool CheckMethod(List src, int checkNum);

        //判定処理の使用箇所
        private static void HasNumberInList(CheckMethod method,
                                            List src,
                                            int number)
        {
            if(method(src, number))
            {
                Console.WriteLine($"{ number }は存在します。");
            }
            else
            {
                Console.WriteLine($"{ number }は存在しません。");
            }
        }

        //メイン処理関数
        static void Main(string[] args)
        {
            //チェック対象のリスト
            var list = new List()
            {
                1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
            };

            //判定数値の入力
            Console.WriteLine("数値を入力してください。");
            var input = Convert.ToInt32(Console.ReadLine());

            //判定処理の実行
            HasNumberInList(
                delegate (List src, int num)
                {
                    foreach(var item in src)
                    {
                        if(item == num)
                        {
                            //同じ数値があったら真
                            return true;
                        }
                    }
                    //同じのがなければ偽
                    return false;
                },
                list,
                input);
            Console.ReadLine();
        }
    }
}

ソースコードが書いたらアプリケーションを実行してみてください。なお、「数値」に変換できる文字以外を入力したら落ちますのでお気を付けください。デリゲートに絞りたかったので例外判定は入れていません。

まずは例のごとくデリゲートの宣言部分を見ていきましょう。以下が対象の記述になります。これについては、これまでと同様ですので特段解説を加える必要がないかと思います。

//デリゲート
delegate bool CheckMethod(List src, int checkNum);

次はデリゲートを引き受けている場所です。第一引数がデリゲートとなっており、第二・第三はデリゲートで使用する引数を想定しています。

//判定処理の使用箇所
private static void HasNumberInList(CheckMethod method,
                                    List src,
                                    int number)
{
    if(method(src, number))
    {
        Console.WriteLine($"{ number }は存在します。");
    }
    else
    {
        Console.WriteLine($"{ number }は存在しません。");
    }
}

では、最後に需要なメイン処理内での匿名メソッドの記述箇所をみていきます。「static void Main(string[] args)」処理内の以下の記述に注目してみてください。

//判定処理の実行
HasNumberInList(
    delegate (List src, int num)
    {
        foreach(var item in src)
        {
            if(item == num)
            {
                //同じ数値があったら真
                return true;
            }
        }
        //同じのがなければ偽
        return false;
    },
    list,
    input);

前回の「C# ゼロから理解するラムダ式:匿名メソッド(無名関数)を書く方法 #7」と同様に匿名メソッドはメソッドの呼び出し元で処理内容を記述することができます。匿名メソッドは処理を引数として記述するため、読みづらくなってしまうので「改行」を上手く使って書いていきましょう。

「delegate」キーワードの後に引数を列挙して、実際の処理部分を記述します。今回はリスト(第二引数)の要素を回しながら第三引数の値が存在していたら真、存在していなければ偽とするような処理にしています。

戻り値を持つ場合のデリゲートでは、戻り値の型を明確に記述している訳ではなく、デリゲートの定義部分にて戻り値の記載があるのみです。ここは混乱ポイントかもしれないので、注意しておいたほうがよいかもしれませんね。

以上、匿名メソッドが戻り値を持つ場合について紹介しました。今回はbool型で書きましたが、これがstringやintなどになっても同様なので書き方は覚えておきましょう。「呼び出し元で処理を書く」という発想は今後の連載内容にも繋がる内容なので復習しておいてください。