C#/いまさらヒトに聞けないこといろいろ/デリゲート で出てきた例(ちょっと整理しますが) をつかって、汎用的なデリゲート、Action/Funcの使い方をメモっておきます ちょっと整理 †C#/いまさらヒトに聞けないこといろいろ/デリゲート のソースをもっとシンプルに整理してみます namespace ConsoleApplication1 { delegate int Calculator(int x, int y);//delegateの宣言 class Program { static void Main(string[] args) { calc(2, 3, methodPlus); calc(2, 3, methodMult); } public static void calc(int x, int y, Calculator instance) { int result = instance(x, y); Console.WriteLine(result); } public static int methodMult(int x, int y) { return x * y; } public static int methodPlus(int x, int y) { return x + y; } } } 汎用的なデリゲートFunc †上では delegate int Calculator(int x, int y); というデリゲートを宣言しましたが、引数がint,int,戻り値がint、っていう汎用的なデリゲート Func<int, int, int> を使うことで、ソースは以下のように書き直すことができます namespace ConsoleApplication1 { //delegate int Calculator(int x, int y); //コメントアウトしちゃう class Program { static void Main(string[] args) { calc(2, 3, methodPlus); calc(2, 3, methodMult); } public static void calc(int x, int y, Func<int, int, int> instance) { int result = instance(x, y); Console.WriteLine(result); } public static int methodMult(int x, int y) { return x * y; } public static int methodPlus(int x, int y) { return x + y; } } } ソースからデリゲートの宣言を消すことが出来ました。こう書くと、いかにも関数を渡してるってかんじになりますねぇ。 いろいろな書き方 †これら、全部おんなじ意味です calc(2, 3, methodPlus); // メソッドを渡す calc(2, 3, new Func<int, int, int>(methodPlus)); // newして、渡す calc(2, 3, new Func<int, int, int>(delegate(int x, int y) { return x + y; })); // メソッドをその場で定義 calc(2, 3, new Func<int, int, int>((int x, int y) => { return x + y; })); // ラムダ式 calc(2, 3, (int x, int y) => { return x + y; }); // ラムダ式で、デリゲート名を省略 calc(2, 3, (x, y) => { return x + y; }); // ラムダ式は型を省略できる calc(2, 3, (int x, int y) => x + y); 戻り値のない汎用デリゲート Action †つぎにActionデリゲートですが、こちらは戻り値のないFuncってかんじです using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { public class Program { static void Main(string[] args) { new Program().execute(); } public void StringAction(string str) { Console.WriteLine("StringAction method start."); Console.WriteLine(str); Console.WriteLine("StringAction method end."); } public void execute() { // GenericsなdelegateをStringとして宣言 Action<String> StringActionDele = new Action<String>(StringAction); //Action<String> StringActionDele = StringAction; // <-こういう書き方もしていい // delegate経由でメソッドを実行 StringActionDele("StringActionDeleを直接呼び出しました"); // メソッドの引数にdelegateインスタンスを渡すこともできる executeAction(StringActionDele); // Anonymousな感じで直接定義してもいい executeAction( new Action<String>(delegate(String str) { Console.WriteLine("Anonymous Delegate method start."); Console.WriteLine(str); Console.WriteLine("Anonymous Delegate method end."); }) ); // 最後はラムダ式。Actionなくなった。引数ひとつでvoidを戻すメソッドを // 渡すから、よろしくねって感じになる executeAction((str) => { Console.WriteLine("Delegate method start."); Console.WriteLine(str); Console.WriteLine("Delegate method end."); }); List<string> stringList = new List<string>(); stringList.Add("こんにちは"); stringList.Add("さようなら"); stringList.ForEach(StringActionDele); // このメソッドで「処理」を渡してる } void executeAction(Action<String> actionDelegate) { actionDelegate("StringActionDeleをexecuteAction メソッドから呼び出しました"); } } } 関連リンク †
この記事は 現在のアクセス:3954 |