【C#】Predicate とは | Predicateを定義・使用する方法

モダン・プログラミングでもよく用いられる技術・記法として Predicate と呼ばれるものがあります。Predicate はbool値を戻り値にもつデリゲートに近い機能の一種です。ラムダ式でよく用いられることがあり、「【C#】ラムダ式を定義して使用する方法 | サンプル付き」ではラムダ式の書き方を紹介しています。

実際のエンジニアでもラムダ式が苦手という人もいるので何回も復習しておくとよいかと思います。

この記事では「Predicate」というものを解説していきます。Predicateはラムダ式を応用した「LINQ」に繋がる内容となるので、身に着けておきましょう。それに加えて、ラムダ式で記述することでシンプルさを求めた書き方ができるというメリットもあるので覚えておきたい記述方法になります。

Predicateとは

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

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

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

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

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

Predicateを書く方法

コンソールアプリケーションでPredicateのサンプルを作成してみました。

using System;

namespace App01
{
    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);

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