C# ゼロから理解するラムダ式:C#におけるデリゲートの基礎知識 #3

前回の連載記事でも書きましたが、ラムダ式にたどり着くには、その過程もしっかりと学ぶのがオススメです。シンプルに記述できるC#のラムダ式は「デリゲート」という技術からスタートしました。

ラムダ式にたどり着く旅は、その最初の一歩である「デリゲート」を学ぶことから始まります。いまでこそラムダ式が生まれたことにより、あまり使われることが少なくなった記述方法ですが、その根底にある考え方は「すべての始まり」なので、しっかりと学習しておきます。

デリゲートの基本知識

まずは「デリゲート」とは何か、という部分から解説していきます。「デリゲート(delegate)」とは英語で「委任する、委譲する、委託する、委嘱する」といった意味を持つ単語です。プログラミング的な意味でのデリゲートは「メソッドを参照を可能とする型」という感じです。

厳密には「処理をカプセル化する」という表現方法が正しいのですが、要するに「データでなく処理を持っている型」と考えておくとスッキリするかなと思います。デリゲートの「委任・委譲」という考え方は、処理を「委任」するという意味合いで、「他で記述された処理に実際の挙動を任せる」という意味になります。

デリゲートを使うためには

「デリゲート」を使用してC#のプログラミングを記述するには「デリゲート型」と呼ばれる変数を使用しなくてはなりません。デリゲートが型の変数を宣言することで、「処理の中身を入れる箱」を作成でき、その中に処理を格納することが可能となります。

delegate型の変数

実際の処理部分は箱の中身として記述された(渡された部分)を使用して処理をします。デリゲートは「箱」を定義することであり、その処理の中身は別の部分で記述できると覚えておきましょう。デリゲート型の変数は以下のようにして定義できます。

delegate 戻り値の型 デリゲート型名(引数リスト);

実際では以下のようにデリゲート型の変数を記述します。実際のソースコードでは以下のような形式でデリゲートを記述します。

delegate void WriteConsole(string str);

上記のようなデリゲート変数の場合、string型の引数を1つ取り、何も戻さない(void型)メソッドと紐づけて使用できます。delegateキーワードを使うことにより「カプセル化された処理を使用します」という宣言になるのです。それ以外は通常のメソッドの定義と同様の記述になります。

どうしてデリゲートが重要なのか

それでは、「デリゲート」がどうして重要になるのかを解説していきます。「デリゲート」の重要な部分は「処理をカプセル化できる」という部分に集約されます。処理をカプセル化することで変数のように扱うことができ、必要な時に実行できるという柔軟性を持つようになるからです。

その考え方としてデリゲート型の宣言が必要になります。これが処理を入れる「箱」だけ作っておいて、必要な時に必要な処理を詰めることができます。デリゲート型の変数にするだけで「メソッドが変数のように扱える」という部分がミソなのです。

この考え方により処理を可変的に代入できるだけでなく、処理を必要な時まで持ちまわることができるようになりました。この考え方がLINQなどに脈々と受け継がれていくことになります。

またそこから発展して、メソッドの引数としてデリゲートを「外側から引き渡せる」ようになっていきます。メソッド内で実行したい処理を、外側から引数で渡せることにより、処理の書き方に柔軟性を与えられます。

「カプセル化できる」の意味をすぐに理解する必要はありません。また、書き方の柔軟性が増すというメリットも今の段階ではピンと来ないかもしれません。それについては今後、当連載を通してコードを書きながら理解してもらえればよいと思っています。