ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

デリゲート

プログラミングC# p286

12章から「デリゲートとイベント」ということで、C#のウリの一つ(?)であるデリゲートの説明になるわけですが、のっけから、

例えば州知事が亡くなった場合、

とか不吉な出だしになってます。
イベント処理で使うのだということはなんとなく分かるのですが、こまごました説明を読んでも良く分からないので、12.1に書いてある

デリゲートの機能は、C++など多くの言語においての関数ポインタやメンバ関数を指すポインタとほぼ同じものです。

を元にサンプルを書いてみる。
実は、先日書いた関数を関数に渡す@C言語のエントリは、このコメントから着想しています。
で、サンプル。

using System;

class FunctionPointer
{
        public delegate int twoitem(int a, int b);

        public static int add(int a, int b)
        {
                return a + b;
        }

        public static int sub(int a, int b)
        {
                return a - b;
        }

        static void Main(string[] args)
        {
                // 関数ポインタを定義
                FunctionPointer.twoitem fp;

                fp = new FunctionPointer.twoitem(FunctionPointer.add);
                Console.WriteLine("result = {0}", fp(5, 3));

                fp = new FunctionPointer.twoitem(FunctionPointer.sub);
                Console.WriteLine("result = {0}", fp(5, 3));
        }
}

結果はこう。

result = 8
result = 2

delegateっちゅうのは、要はメソッド自体の入れ物で、カッコ付ければコールできると。まあそんな感じでしょう。
Java的にはインタフェース使って書くようなところでしょう。
それはこんな感じ。

public class FunctionPointer
{
        public static void main(String[] args)
        {
                TwoItem ti = new Add();
                System.out.println("result = " + ti.twoitem(5, 3));

                ti = new Sub();
                System.out.println("result = " + ti.twoitem(5, 3));
        }
}

interface TwoItem
{
        public int twoitem(int a, int b);
}

class Add implements TwoItem
{
        public int twoitem(int a, int b)
        {
                return a + b;
        }
}

class Sub implements TwoItem
{
        public int twoitem(int a, int b)
        {
                return a - b;
        }
}

結果は同じ。

result = 8
result = 2

C#で書いても似たようなものだと思います。インタフェースでなくデリゲートな理由は、p287にもあるように、

これはインターフェイスを使って実現できるでしょう。しかしデリゲートはインターフェイスよりも小さく、粒度が細かいのです。

というわけで、interfaceとか、その実装classとかを用意しなくても、少ないコード量で多態性を実現できる仕組みと捕らえるのが良いようです。