移譲先リストの変更
delegateに含まれる移譲先リストは、いつでも追加削除できる。追加には「+演算子」や「+=演算子」を使い、削除には「−=演算子」を用いる。以下はリストの追加と削除を行うサンプル・ソースである。
1: using System;
2:
3: namespace ConsoleApplication29
4: {
5: delegate void Sample();
6: class Class2
7: {
8: private string name;
9: public Class2( string name )
10: {
11: this.name = name;
12: }
13: public void method()
14: {
15: Console.WriteLine(name);
16: }
17: }
18: class Class1
19: {
20: static void Main(string[] args)
21: {
22: Sample samples = new Sample( new Class2("test1").method );
23: Sample sample2 = new Sample( new Class2("test2").method );
24: Sample sample3 = new Sample( new Class2("test3").method );
25: Sample sample4 = new Sample( new Class2("test4").method );
26: Console.WriteLine("call 1 method");
27: samples();
28: samples += sample2;
29: samples += sample3;
30: samples += sample4;
31: Console.WriteLine("call 4 methods");
32: samples();
33: samples -= sample2;
34: Console.WriteLine("call 3 methods");
35: samples();
36: }
37: }
38: } |
|
リストの追加と削除を行うサンプル・プログラム10 |
「−=演算子」によって、delegateの呼び出しリストから、登録されているメソッドを削除することができる。 |
これを実行すると以下のようになる。
|
サンプル・プログラム10の実行結果 |
1つのdelegateに4つのメソッドを登録して呼び出した後、2番目のメソッドだけを削除して再度呼び出している。
|
27行目の段階では、samplesには1つしかメソッドが登録されていないので、それだけが呼ばれる。しかし、32行目の段階では、4つのメソッドが登録されていて、それらのすべてが呼び出される。しかし、33行目で1つの移譲先を取り除いているので、35行目の段階では、3つのメソッドが呼び出されている。
delegate型の同一性
delegateで委譲するメソッドは戻り値と引数が一致していればよいと書いたが、delegate型同士は、戻り値と引数が一致していても、同じとは見なされない。以下のサンプル・ソースはコンパイルできない誤った例である。
1: using System;
2:
3: namespace ConsoleApplication30
4: {
5: delegate void Sample1();
6: delegate void Sample2();
7: class Class1
8: {
9: public static void method()
10: {
11: Console.WriteLine("Hello!");
12: }
13: static void Main(string[] args)
14: {
15: Sample1 samples = new Sample1( Class1.method );
16: Sample2 sample2 = new Sample2( Class1.method );
17:
18: // エラー: 演算子 '+=' を 'ConsoleApplication30.Sample1' と'ConsoleApplication30.Sample2' 型のオペランドに適用することはできません。
19: samples += sample2;
20:
21: samples();
22: }
23: }
24: } |
|
delegateの誤った使い方を示すサンプル・プログラム11 |
メソッドの戻り値と引数が一致していても、異なるdelegate型のインスタンスを合成することはできない。 |
19行目のように、異なるdelegate型のdelegateインスタンスを1つのリストにまとめることはできない。たとえ、戻り値と引数が一致していても、である。
まとめ
delegateは込み入ったメソッド呼び出しをスマートに解決する能力を秘めた、強力な機能である。クラスと継承を使って実現するのに比べれば、非常にコンパクトでスマートといえる。メソッド呼び出しのコードから呼び出し先に関する詳細情報を隠してしまうので、うまく活用すればソースコードがシンプルで読みやすくなる可能性もある。理解して使いこなすのもたいへんだと思うが、ぜひチャレンジしてみていただきたい。
さて、次回はエラー処理のかなめとなる例外について取り上げたいと考えている。
それでは次回もLet's See Sharp!
Insider.NET 記事ランキング
本日
月間