ITコンサルの日常

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

続・マルチキャストデリゲート

プログラミングC# p316

マルチキャストデリゲートの戻り値はどうするかという問題。
昨日の無名メソッドの例を流用して、マルチキャストデリゲートの戻り値を表示してみる。

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 = FunctionPointer.add;

                fp += FunctionPointer.sub;

                fp += delegate(int a, int b)
                {
                        return a * b;
                };

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

結果はこう。

result = 15

どうやら、最後に実行されたメソッドの戻り値がそのまま返されるらしい。
つまり、最後に実行されたメソッド以外(ここではaddとsub)の戻り値が、このままでは活用できない。
そこで、デリゲートをばらばらに実行する方法というのがある。
それが、System.Delegate#getInvocationList。
特に意味はないが、この機能を使って各計算結果の合計(total)を算出してみる。

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 = FunctionPointer.add;

                fp += FunctionPointer.sub;

                fp += delegate(int a, int b)
                {
                        return a * b;
                };

                int total = 0;
                foreach(FunctionPointer.twoitem ptr in fp.GetInvocationList())
                {
                        int result = ptr(5, 3);
                        Console.WriteLine("result = {0}", result);

                        total += result;
                }

                Console.WriteLine("total = {0}", total);
        }
}

結果はこう。

result = 8
result = 2
result = 15
total = 25

個別のメソッドの戻り値、および、その合計を表示することが出来た。

デリゲートの非同期呼び出し

プログラミングC# p320

デリゲートを非同期に呼び出して、結果を別のメソッドで処理します。ちょっとAjaxというかXmlHttpRequestっぽい。

using System;
using System.Threading;

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;
        }

        private static void DisplayResult(IAsyncResult ar)
        {
                // キャストして元のデリゲートを取得する
                FunctionPointer.twoitem ptr = (FunctionPointer.twoitem)ar.AsyncS
tate;

                int result = ptr.EndInvoke(ar);
                Console.WriteLine("result = {0}", result);
        }

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

                fp = FunctionPointer.add;

                fp += FunctionPointer.sub;

                fp += delegate(int a, int b)
                {
                        return a * b;
                };

                foreach(FunctionPointer.twoitem ptr in fp.GetInvocationList())
                {
                        ptr.BeginInvoke(5, 3, new AsyncCallback(DisplayResult),
ptr);
                }

                Console.WriteLine("非同期呼び出し完了");

                Thread.Sleep(1000);
        }
}

結果はこう。

非同期呼び出し完了
result = 8
result = 2
result = 15

BeginInvokeで非同期デリゲート呼び出しを行い、その引数で渡したAsyncCallbackのメソッドでデリゲートの結果に対して処理を行う。
BeginInvokeはライブラリリファレンスには載ってませんが、デリゲートの引数 + AsyncCallback + デリゲートオブジェクト自身を引数に受け取るようです。
ちなみに最後にSleepを入れたのは、これを入れなかった場合何も表示されなかったからです。多分、非同期メソッド呼び出しが行われる前に、Main自体が終了してしまっているようなのですが、そんなのアリなんですかね?良く分かりません。。