delegate


SYNTAX [attributes] [modifiers] delegate result-type type ([formal-parameters]); DESC 関数ポインタは型保証がなく、リスクが生じるのでオブジェクト指向には適さない そこで、C# ではデリゲートという機能がつかう デリゲートの宣言は名前空間やクラスのメンバ空間などで宣言できる。 クラスのメンバ空間で宣言した場合も、インスタンスとの関わりはない。 デリゲート型とは System.Delegate の派生クラスを指す。 重要なことですが、Delegate クラスはデリゲート型ではない。 Delegate クラスの派生クラスがデリゲート型になる。 デリゲート型は 暗黙的に sealed となっている。
public abstract class Delegate : ICloneable, ISerializable
デリゲートする関数はシグネチャが同じなら、インスタンスのメソッドでもよい。 この時、デリゲートはインスタンスの情報と共にメソッドの情報を格納する。 コールバックの仕様などにあわせて、目的のシグネチャを指定できます // delegate 型をつくる. // delegate の Instance を作成することで使用する. new delegate_type( expression // delegation で呼びだす Method ); // expression に指定するメソッドは、必ずデリゲート型と同じシグネチャでなければなりません // シグネチャが同じであれば、型が保証されるのでほかに制約されるものはありません デリゲートを用いてメソッドにアクセスする デリゲートの識別子と () を用いて、通常のメソッドのように呼び出すことができる
class Test { static void Main() { // Delegator を作成して, void、パラメータ無しのメソッドの位置を保有する。 TestCallback test = new TestCallback(Test); // callback を呼ぶ。 test(); } static void Test() { System.Console.WriteLine("Test on your lap"); } }
delegateとは何か POINT 関数ポインターのこと。 委譲という言葉が分かりにくいと思うなら、「代表者」と考えてもよい。 何かの処理を実行させたいときに、直接処理機能を持つメソッドを呼び出すのではなく、 代表者に処理を求めるのである。代表者は処理機能自体は持っていないが、 それを処理できる適切なメソッドを知っていてそのメソッドに処理要求を渡す。 EventHandler pFoo; といいかえれば OK. 「 クラスA 」の「 メソッドa 」は自分では何も処理せず、 常に「 クラスB 」の「 メソッドb 」に処理をゆだねるとしよう。 このような場合、「 メソッドa 」の中に「 メソッドb 」を呼び出すコードを書けばよいので、 特別な機能は何も必要がない。 A::methodA() { // ここを固定したくない B::methodB(); } POINT このように常に処理をゆだねる相手が決まっているとは限らないし、 相手が常に1つとも限らない この状況に対応するために delegate を使う。 WARNING delegateの機能はeventの機能によく似ている 実際に、event機能はdelegate機能を利用して作られている。 delegateとeventは想定される使われ方が違っており 機能面でも違いがある。 delegateは処理を他にゆだねるものだが eventはクラス内の出来事を外部に伝えるもの。 どちらか一方だけ覚えて 他方は使わないという方法はうまくいかない。 関数ポインタと似ているのは役割であって 関数ポインタの機能とdelegateの機能が同じではない。 C言語で関数ポインタを使っていた場面で、 C#ではdelegateを使うかもしれないが 具体的な機能はまったく違うということ // delegate経由でメソッドを呼び出すサンプル using System; namespace ConsoleApplication20 { // delegate 型だよ - ^ ^/ // Signature は int ( int, int ); だよ. ^ ^/ // そして 名前は Sample だよ. ^ ^/ // delegate のデータ型を決める。 // 呼び出せるのは、あくまで同じ戻り値、同じ引数のメソッドのため型を決めておく。 // データ型の名前となる。 // delegate の宣言には、public や private などのキーワードも付けることもできる。 delegate int Sample( int x, int y ); class Class2 { // Signature が同じであることが POINT public int method( int x, int y ) { return x*y; } } class Class1 { static void Main(string[] args) { Class2 instance = new Class2(); // 代理人を作成する際に, Method をもらう. ( Isntance つき. ) // delegate を作成して instance のメソッドを渡す。 Sample sample = new Sample( instance.method ); // 代理人経由で呼び出す. int result = sample( 2, 3 ); Console.WriteLine( result ); } } } POINT delegate を使って異なる処理が一元化できる。
using System; namespace ConsoleApplication21 { delegate int Sample( int x, int y ); class Class2 { public int methodMult( int x, int y ) { return x*y; } public int methodPlus( int x, int y ) { return x+y; } } class Class1 { // delegate 型を外からもらうことが可能. // 計算方法を外へ出すということ。 public static void calc( int x, int y, Sample calcMethod ) { // calcメソッドで、さまざまな計算を実行させたい // このdelegateのインスタンスの移譲先として指定するメソッドを入れ替えれば 計算内容も変わる int result = calcMethod( x, y ); Console.WriteLine( result ); } static void Main(string[] args) { Class2 instance = new Class2(); calc( 2, 3, new Sample( instance.methodMult ) ); calc( 2, 3, new Sample( instance.methodPlus ) ); } } }