続・マルチキャストデリゲート
プログラミング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自体が終了してしまっているようなのですが、そんなのアリなんですかね?良く分かりません。。