// 下階層用テンプレート
#topicpath
----
//ここにコンテンツを記述します。
#contents

**C#はDelegateを言語でサポートしてるみたい [#ib7cd4ac]
C#では「delegate」という機構で、実装の切替をすることが言語仕様でサポートされてるみたいです。いわゆるオブジェクト指向でいう、実装をインタフェースつかって切り替えるってヤツです。Javaで書くとこんな感じ。
 package console_application1;
 
 public class Program {
     public static void main(String[] args) {
         Base plus = new Plus();
         Base mult = new Mult();
         calc(2, 3, plus);
         calc(2, 3, mult);
     }
 
     public static void calc(int x, int y, Base instance) {
         int result = instance.method(x, y);
         System.out.println(result);
     }
 }
 
 interface Base {
     int method(int x, int y);
 }
 
 class Plus implements Base {
     public int method(int x, int y) {
         return x + y;
     }
 }
 
 class Mult implements Base {
     public int method(int x, int y) {
         return x * y;
     }
 }


もちろんC#でdelegateを使わないで書くこともできます。こんな感じですね。

 using System;
 
 namespace ConsoleApplication1
 {
   class Program
   {
     static void Main(string[] args)
     {
       Base plus = new Plus();
       Base mult = new Mult();
       calc(2,3, plus);
       calc(2,3, mult);
     }
 
     public static void calc(int x, int y, Base instance)
     {
       int result=instance.method(x,y);
       Console.WriteLine(result);
     }
   }
 
   interface Base
   {
      int method(int x, int y);
   }
 
   class Plus : Base
   {
     public  int method(int x, int y)
     {
       return x + y;
     }
   }
   
   class Mult : Base
   {
     public  int method(int x, int y)
     {
       return x * y;
     }
   }
 }

JavaとC#はほとんど書き方が同じでJava使いの私としてはラクチンです


さてこれをC#のdelegateでかくとこんな感じみたいです

 using System;
 
 namespace ConsoleApplication1
 {
   delegate int Calculator(int x, int y);//delegateの宣言
   class CalculatorBase
   {
     public int methodMult(int x, int y)
     {
       return x * y;
     }
     public int methodPlus(int x, int y)
     {
       return x + y;
     }
   }
 
   class Program
   {
     static void Main(string[] args)
     {
       CalculatorBase calculator = new CalculatorBase();
       calc(2, 3, new Calculator(calculator.methodPlus));
       calc(2, 3, new Calculator(calculator.methodMult));
     }
 
     public static void calc(int x, int y, Calculator instance)
     {
       int result=instance(x,y);
       Console.WriteLine(result);
     }
   }
 }

メソッドの型(?)を
 delegate int Calculator(int x, int y);
って宣言しておいて、実装を
 new Calculator(calculator.methodPlus)
ってコンストラクタで指定するって感じ?JavaのインタフェースつかったDelegateと違うのは指定する実装クラスの型が任意ってコトかなあ??

ちなみに
new Calculator(calculator.methodPlus) の箇所は下記のように省略も出来ます
  calc(2, 3, new Calculator(calculator.methodPlus));
 -> calc(2, 3, calculator.methodPlus);
ちょっとシンプルになります

**匿名クラスっぽくかいてみる [#ha50a611]
 calc(2, 3, new Calculator(calculator.methodPlus));
の箇所はいわゆる匿名クラスみたいな感じで書くこともできます。
 calc(2, 3, new Calculator(delegate(int x, int y)
 {
   return x - y;
 }));
「delegate」て単語を使うって事ですね。


**ラムダ式?ってのもあるらしい [#e0f332e1]
 calc(2, 3, new Calculator((int x, int y) =>
 {
   return x + y;
 }));
こうやってdelegateって単語すら省略できたり、果ては
 calc(2, 3, new Calculator((int x, int y) => x + y));
こういう文法もあるみたいです。

C#ややこしいです(´д`;)


**ちょっと整理 [#j14c57d7]
ソースをもっとシンプルに整理してみます
 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;
     }
   }
 }

** 汎用的なデリゲート? [#xe57c138]
上では
   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;
         }
     }
 }
ソースからデリゲートの宣言を消すことが出来ました。こう書くと、いかにも関数を渡してるってかんじになりますねぇ。

**さっきのようないろいろな書き方 [#p2038bc2]

これら、全部おんなじ意味です
 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);


**関連リンク [#oa8b34d8]
-[[@IT:連載 改訂版 C#入門 第13章 処理を委譲するデリゲート>http://www.atmarkit.co.jp/fdotnet/csharp_abc2/csabc2_013/cs2_013_03.html]]
-[[C#ラムダ式 基礎文法最速マスター − @IT>http://www.atmarkit.co.jp/fdotnet/rapidmaster/rapidmaster_01/rapidmaster_01.html]]
-[[C#のデリゲートとイベントの使い分け>http://tec.jpn.ph/comp/delegateandevent.html]]
-[[C#と諸々 今更 Func デリゲートや Action デリゲートについて一言>http://csharper.blog57.fc2.com/blog-entry-252.html]]
-[[Action(T) デリゲート (System)>http://msdn.microsoft.com/ja-jp/library/018hxwa8.aspx]]
-[[Func(TResult) デリゲート (System)>http://msdn.microsoft.com/ja-jp/library/bb534960]]
-[[ジェネリックなメソッドやデリゲートがもたらす新スタイル − @IT>http://www.atmarkit.co.jp/fdotnet/special/generics02/generics02_02.html]]


----
この記事は
#vote(おもしろかった[4],そうでもない[3])
- C#の中カッコを行変えするのが慣れないなぁ。 -- [[きの]] &new{2010-09-23 (木) 17:14:59};

#comment
#topicpath


SIZE(10){現在のアクセス:&counter;}



トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS