C#の目玉機能として「LINQ」と呼ばれるものがありますが、そのLINQの歴史をさかのぼっていくと、最も根本にあるのが「デリゲート」と呼ばれる技術になります。
ラムダ式をしっかりと理解するためには、最初の一歩である「デリゲート」を学ぶことが重要です。現在ではラムダ式の普及により使用頻度が少なくなったデリゲートですが、これについて学んでおくことは非常に重要です。
デリゲートとは
まずは「デリゲート」とは何か、という部分から解説していきます。「デリゲート(delegate)」とは英語で「委任する、委譲する、委託する、委嘱する」といった意味を持つ単語です。プログラミング的な意味でのデリゲートは「メソッドを参照を可能とする型」という感じです。
厳密には「処理をカプセル化する」という表現方法が正しいのですが、要するに「データでなく処理を持っている型」と考えておくとスッキリするかなと思います。デリゲートの「委任・委譲」という考え方は、処理を「委任」するという意味合いで、「他で記述された処理に実際の挙動を任せる」という意味になります。
デリゲートを使用する方法
「デリゲート」を使用してC#のプログラミングを記述するには「デリゲート型」と呼ばれる変数を使用しなくてはなりません。デリゲートが型の変数を宣言することで、「処理の中身を入れる箱」を作成でき、その中に処理を格納することが可能となります。
delegate型の変数
実際の処理部分は箱の中身として記述された(渡された部分)を使用して処理をします。デリゲートは「箱」を定義することであり、その処理の中身は別の部分で記述できると覚えておきましょう。デリゲート型の変数は以下のようにして定義できます。
delegate 戻り値の型 デリゲート型名(引数リスト);
実際では以下のようにデリゲート型の変数を記述します。実際のソースコードでは以下のような形式でデリゲートを記述します。
delegate void WriteConsole(string str);
上記のようなデリゲート変数の場合、string型の引数を1つ取り、何も戻さない(void型)メソッドと紐づけて使用できます。delegateキーワードを使うことにより「カプセル化された処理を使用します」という宣言になるのです。それ以外は通常のメソッドの定義と同様の記述になります。
なぜデリゲートが重要なのか
それでは、「デリゲート」がどうして重要になるのかを解説していきます。「デリゲート」の重要な部分は「処理をカプセル化できる」という部分に集約されます。
処理をカプセル化することで変数のように扱うことができ、必要な時に実行できるという柔軟性を持つようになるからです。その考え方としてデリゲート型の宣言が必要になります。
これが処理を入れる「箱」だけ作っておいて、必要な時に必要な処理を詰めることができます。
デリゲート型の変数にするだけで「メソッドが変数のように扱える」という部分がミソなのです。この考え方により処理を可変的に代入できるだけでなく、処理を必要な時まで持ちまわることができるようになりました。
この考え方がLINQなどに脈々と受け継がれていくことになります。またそこから発展して、メソッドの引数としてデリゲートを「外側から引き渡せる」ようになっていきます。メソッド内で実行したい処理を、外側から引数で渡せることにより、処理の書き方に柔軟性を与えられます。