C# ゼロから理解するラムダ式:C#でPredicateを書く方法 #10

前回の「C# ゼロから理解するラムダ式:C#でラムダ式を書く方法 #9」ではラムダ式の書き方を全般的に見てきました。ラムダ式で記述することで、シンプルさを求めた書き方をすることができますので、慣れるまで使ってみてください。

それに引き続いて今回は「Predicate」を学びます。これまでは主にラムダ式までの学習をしてきましたが、ここからはラムダ式を応用した「LINQ」に繋がる内容となっていくのでしっかりと身に着けておきましょう。

逆にいうとLINQが苦手だと思う人はここからが頑張りどころですので、一緒に苦手を頑張っていきましょう。しっかりと学べばLINQも得意になるはずです。というわけでPredicateの基本から学んでいきます。

C#におけるPredicateとは

ここで新しく学ぶのは「Predicate」と呼ばれるものです。Predicateとは以下のような特徴を持っています。

  • C# 1.0で実装されているデリゲートに近い機能
  • C# 2.0でGenericと共に実装された機能
  • 引数を1つ渡して処理を実行可能
  • 戻り値はbool型である

C#のdllに残されているコメントを見ると以下のように記述されていました。

条件のセットを定義し、指定されたオブジェクトがその条件を満たしているかどうかを判断するメソッドを表わします。

Predicateは引数を1つ取り、bool値を返すデリゲートの「テンプレート」だと思うのが一番理解しやすいかなと思います。デリゲートを毎回定義する必要がなく、すぐに使えるテンプレートということです。

C#でPredicateを書く方法

それでは実際にPredicateを書いていきます。新規のコンソールアプリケーションを作成して以下のコードを記述してみてください。記述できたら実際に動かして挙動を確認してみましょう。

using System;

namespace App09
{
    class Program
    {
        //メインの処理
        static void Main(string[] args)
        {
            Console.WriteLine("数値を入力してください。");
            int input = Convert.ToInt32(Console.ReadLine());

            //predicateの実行して、メッセージを取得して表示する
            string message = CheckNumber((x) => x >= 10, input);
            Console.WriteLine(message);
            Console.ReadLine();
        }

        ///数字をチェックする
        private static string CheckNumber(Predicate method, int input)
        {
            if(method(input))
            {
                return "10以上の数です。";
            }
            else
            {
                return "10未満の数です。";
            }
        }
    }
}

上記のアプリケーションにおけるPredicateを宣言している箇所は以下になります。第一引数にてPredicateを宣言しています。変数(メソッド名)は「method」としています。第二引数の値をPredicateの引数として処理を実行し、戻り値のbool値で分岐をするようにしています。

private static string CheckNumber(Predicate method, int input)

そして実際にPredicateの実処理を記述しているのが以下の箇所になります。第一引数で書いているラムダ式がPredicateの実処理部分です。10以上ならTrueになるようにしました。

string message = CheckNumber((x) => x >= 10, input);

とはいえ、このアプリケーションでは、Predicate出の戻り値であるメッセージが「10以上、10未満」と謳っているいるため、あんまりPredicateにする意味はないのですが・・・。とはいえ、このようにしてPredicateを使用します。

Predicateは「戻り値がbool型」という制約があるので、戻り値をきちんと持つように処理を記述する必要があります。ラムダ演算子では単行の式の場合は「=>」で「return」の役割も持っているので記述は不要になります。複数行の場合({ … }で記述する場合)は「return x >= 10」と書く必要があります。

また、Predicateは処理をカプセル化できるので、以下のように処理を変数に代入してからメソッドに引き渡すことも可能です。個人的には引数に直接ラムダ式で記述するほうがラクだと感じます。

Predicate method = (x) => x >= 10;

なおラムダ式で引数の処理内容を直接的に記述していますが、匿名メソッドでも同様の内容が欠けますので参考までに以下に紹介しておきます。

string message = CheckNumber(delegate (int x)
{
    return x >= 10;
},
input);

上記のように匿名メソッドでも記述可能ですが、ラムダ式のほうが記述量が少なくなっているのが分かりますね。匿名メソッドにも慣れていない人は、ラムダ式と匿名メソッドの両方で書くようにチャレンジしてみてください。いい練習になりますよ。