C#のdelegateとevent

(2017-03-12)

delegate

カプセル化するためのdelegate(移譲)メソッドに使う型。

public class Converter{

	private static double defaultConvert(double num){
		return num;
	}

	public delegate double Convert(double num);
	public Convert convert = defaultConvert;

	public double run(double num){
		return convert (num);
	}
}

匿名メソッドやラムダ式を渡すこともできる。

var conv = new Converter ();

print (conv.run (2)); // 2

// 匿名メソッドの例
conv.convert = delegate(double input)
{
    return input + 1;
};
print (conv.run (2)); // 2 + 1 = 3

// ラムダ式の例
conv.convert = s => s * s;
print (conv.run(2)); // 2 * 2 = 4

event

宣言元でしか呼べないマルチキャストデリゲート。+=でsubscribeして-=で解除する。

public delegate void RunEventHandler(double num);
public event RunEventHandler RunEvent;

public double run(double num){
    if (RunEvent != null) {
        RunEvent (num);
    }
    return convert (num);
}

subscribeしたものは全て呼ばれる。

private void runHook(double num){
    print("b: " +  num);
}

var conv = new Converter ();
conv.RunEvent += s => print ("a: " +  s); // Subscribe a
conv.run (2); // a: 2

conv.RunEvent += runHook; // Subscribe b
conv.run (3); // a: 3, b: 3

conv.RunEvent -= runHook; // Unsubscribe b
conv.run (4); // a: 4

// error
// conv.RunEvent (); 

.NET Frameworkのクラスライブラリの全てのイベントでは EventHandlerを使っていて、 ユーザー定義のコードでもこのパターンを使うのが推奨されている

public delegate void EventHandler<TEventArgs>(
	object sender,
	TEventArgs e
)