デリゲート


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

デリゲート

関数ポインタの配列のような扱いをするものである。

デリゲートは呼び出しリストを内部で持っており、宣言時のシグネチャと同じ関数を登録していく。(ただし、シグネチャは完全に一致しなくても良い)

delegate void SomeMethod(int a); // int型引数と戻り値の型がvoidのデリゲート

デリゲートのシグネチャはポリモーフィズムを考慮している。
次のように、object型を引数に持つ場合、object型を派生したクラスならシグネチャは一致する為、デリゲートへ登録できる。

delegate void SomeMethod(object a); // object型引数と戻り値の型がvoidのデリゲート
 
SomeMethod m = a;
m += b;
 
static void A(string a);
static void B(int b);

デリゲートへの登録・削除

デリゲートが呼び出す関数をエンティティと呼ぶ。
2つ以上のエンティティを呼び出しリストに登録したデリゲートをマルチキャストデリゲートと呼ぶ。

delegate void SomeMethod(int a);
 
class MainTest {
	static void Main() {
		SomeMethod d = new SomeMethod(A); // 初期化時にエンティティを追加
		// C#2からは、次のようにも記述できる
		// SomeMethod d = A;
 
		d(10); // デリゲートの呼び出し
 
		Message myObj = new Message("インスタンスです");
		d += new SomeMethod(myObj.SomeMethod); // インスタンスメソッドもデリゲートに登録可能
 
		d(10); // デリゲートの呼び出し
	}
 
	static void A(int a) {
		Console.Write("A({0})",a);
	}
}
 
class Message {
	String message;
	public Message(String message) {
		this.message = message;
	}
 
	public void SomeMethod(int a){
		Console.Write("{0} - {1}",a,this.message);
	}

デリゲートへ登録したエンティティを呼び出しリストから削除するには「-=」を使用します。

delegate void SomeMethod(int a);
 
class MainTest {
	static void Main() {
		SomeMethod d = new SomeMethod(A); // 初期化時にエンティティを追加
		// C#2からは、次のようにも記述できる
		// SomeMethod d = A;
 
		d = new SomeMethod(B);
 
		d(10); // デリゲートの呼び出し(A()とB()が呼び出される)
 
		d -= A;
 
		d(10); // デリゲートの呼び出し(B()だけが呼び出される)
	}
 
	static void A(int a) {
		Console.Write("A({0})",a);
	}
	static void B(int a) {
		Console.Write("B({0})",a);
	}
}

同じデリゲートインスタンスならば、デリゲートとデリゲートを組み合わせる事ができる。

delegate void SomeMethod(int a);
 
class MainTest {
	static void Main() {
		SomeMethod d1 = A;
		SomeMethod d2 = B;
 
		SomeMethod all = d1 + d2; // デリゲートの足し算
 
		all(10); // デリゲートの呼び出し(A()とB()が呼び出される)
	}
 
	static void A(int a) {
		Console.Write("A({0})",a);
	}
	static void B(int a) {
		Console.Write("B({0})",a);
	}
}

同期実行・非同期実行

デリゲートの実行は「同期実行」で行われ、その順番は呼び出しリストに登録された順となります。

非同期でデリゲートを呼び出すと、デリゲートの呼び出し元はデリゲートの処理が終了するまで待つ必要が無くなります。
ただし、マルチキャストデリゲートは非同期でデリゲートを実行することはできません。

デリゲートを非同期で呼び出すには、デリゲートクラスのメンバ関数であるBeginInvoke()を使用してデリゲートを呼び出します。

delegate void SomeMethod(int a);
 
class MainTest {
	static void Main() {
		SomeMethod d1 = A;
 
		// 非同期でデリゲートを実行する
		IAsyncResult ar = d1.BeginInvoke(1, null, null);
 
		d1.EndInvoker(ar); // デリゲートの終了までウエイト
	}
 
	static void A(int a) {
		Console.Write("A({0})",a);
	}
}

読んでいる本


Effective C#

QLOOKアクセス解析

ここを編集