連載
プロフェッショナルVB.NETプログラミング
第23回 処理を委譲するデリゲート
(株)ピーデー
川俣 晶
2002/11/02
|
|
委譲先の合成
デリゲートのインスタンスは委譲先メソッドに関する情報を含むが、この情報は「リスト」として保持される。つまり、委譲先メソッドは複数指定することもできるというわけである。以下は2つの委譲先メソッドを指定した例である。
1: Delegate Sub SampleDelegate()
2:
3: Public Class Class2
4: Public Sub Method1()
5: Trace.WriteLine("Method1 called")
6: End Sub
7: Public Sub Method2()
8: Trace.WriteLine("Method2 called")
9: End Sub
10: End Class
11:
12: Public Class Form1
13: Inherits System.Windows.Forms.Form
14:
15: …Windows フォーム デザイナで生成されたコード…
16:
17: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
18: Dim instance As New class2()
19: Dim sample1 As SampleDelegate = AddressOf instance.Method1
20: sample1()
21: Dim sample2 As SampleDelegate = AddressOf instance.Method2
22: sample2()
23: Dim sample3 As SampleDelegate = System.Delegate.Combine(sample1, sample2)
24: sample3()
25: End Sub
26: End Class
|
|
1つのデリゲートに2つのメソッドを指定したサンプル・プログラム10 |
これを実行すると以下のようになる。
1: Method1 called
2: Method2 called
3: Method1 called
4: Method2 called
|
|
サンプル・プログラム10の実行結果 |
ここでポイントになるのは、23行目のSystem.Delegate.Combineメソッドである。これはSystem.Delegateクラスの共有メソッドである。ここでSystemというキーワードが必要になるのは、ただDelegateとだけ記述すると、VB.NETのDelegateキーワードとして扱われてしまうためである。このメソッドを使えば、複数のデリゲートを合成した新しいデリゲートを作成できる。つまり、2つのデリゲート・インスタンスが持つ委譲先メソッドのリストが合成され、1つのリストにまとめられる。
このように複数の委譲先メソッドが合成されたデリゲート・インスタンスを、24行目のように呼び出すと、リストに属するすべてのメソッドが呼び出される。複数の処理をまとめて実行させるには便利な機能だが、戻り値を受け取りたい場合は適切ではない。一度にいくつものメソッドを呼び出せるが、受け取れる戻り値は最後に呼ばれたメソッドの戻り値ただ1つだけである。
委譲先リストの変更
デリゲートに含まれる委譲先リストはいつでも追加/削除できる。追加にSystem.Delegate.Combineメソッドを用いることはすでに述べたが、削除する場合はSystem.Delegate.Removeメソッドを用いる。以下はリストの追加と削除を行うサンプル・プログラムである。
1: Delegate Sub SampleDelegate()
2:
3: Public Class SampleClass
4: Private name As String
5: Public Sub New(ByVal name As String)
6: MyBase.New()
7: Me.name = name
8: End Sub
9:
10: Public Sub Method()
11: Trace.WriteLine(name)
12: End Sub
13: End Class
14:
15: Public Class Form1
16: Inherits System.Windows.Forms.Form
17:
18: …Windows フォーム デザイナで生成されたコード…
19:
20: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
21: Dim samples As SampleDelegate
22: samples = AddressOf New SampleClass("sample1").Method
23: Dim sample2 As SampleDelegate = AddressOf New SampleClass("sample2").Method
24: Dim sample3 As SampleDelegate = AddressOf New SampleClass("sample3").Method
25: Dim sample4 As SampleDelegate = AddressOf New SampleClass("sample4").Method
26: Trace.WriteLine("call 1 method")
27: samples()
28: samples = System.Delegate.Combine(samples, sample2)
29: samples = System.Delegate.Combine(samples, sample3)
30: samples = System.Delegate.Combine(samples, sample4)
31: Trace.WriteLine("call 4 method")
32: samples()
33: samples = System.Delegate.Remove(samples, sample2)
34: Trace.WriteLine("call 3 method")
35: samples()
36: End Sub
37: End Class
|
|
委譲先リストの追加と削除を行うサンプル・プログラム11 |
これを実行すると以下のようになる。
1: call 1 method
2: sample1
3: call 4 method
4: sample1
5: sample2
6: sample3
7: sample4
8: call 3 method
9: sample1
10: sample3
11: sample4
|
|
サンプル・プログラム11の実行結果 |
27行目の段階では、samplesには1つしかメソッドが登録されていないので、それだけが呼ばれる。しかし、32行目の段階では、4つのメソッドが登録されていて、それらのすべてが呼び出される。しかし、33行目で1つの委譲先を取り除いているので、35行目の段階では3つのメソッドが呼び出されている。System.Delegate.Removeメソッドは、第1引数のリストから、第2引数のリストのメソッドを取り除く。
デリゲート型の同一性
デリゲートで委譲するメソッドは戻り値と引数が一致していればよいと書いたが、デリゲート型同士は、戻り値と引数が一致していても同じとは見なされない。以下のサンプル・プログラムは実行するとランタイム・エラーで停止する。
1: Delegate Sub SampleDelegate1()
2: Delegate Sub SampleDelegate2()
3:
4: Public Class Form1
5: Inherits System.Windows.Forms.Form
6:
7: …Windows フォーム デザイナで生成されたコード…
8:
9: Public Shared Sub Method()
10: Trace.WriteLine("Hello!")
11: End Sub
12:
13: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
14: Dim samples As SampleDelegate1 = AddressOf Method
15: Dim sample2 As SampleDelegate2 = AddressOf Method
16: samples = System.Delegate.Combine(samples, sample2)
17: samples()
18: End Sub
19: End Class
|
|
異なるデリゲート型を委譲先リストに格納して呼び出すサンプル・プログラム12(実行時にエラーとなる) |
16行目のように、異なるデリゲート型のデリゲート・インスタンスを1つのリストにまとめることはできない。たとえ戻り値と引数が一致していても、である。実行すると「デリゲートは同じ型でなければなりません」というランタイムのエラー・メッセージが出力される。
次回予告
次回はイベントとウィンドウ・アプリケーションの仕組みに関する解説を予定している。
Insider.NET 記事ランキング
本日
月間