|
|
連載
改訂版
プロフェッショナルVB.NETプログラミング
Chapter 11 デリゲート
株式会社ピーデー
川俣 晶
2004/07/22 |
|
|
デリゲートのインスタンスは委譲先メソッドに関する情報を含むが、この情報は「リスト」として保持される。つまり、委譲先メソッドは複数指定することもできるというわけである。以下は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
|
|
リスト11-17 1つのデリゲートに2つのメソッドを指定したプログラム
|
これを実行すると以下のようになる。
1: Method1 called
2: Method2 called
3: Method1 called
4: Method2 called
|
|
リスト11-18 リスト11-17の実行結果
|
ここでポイントになるのは、23行目のSystem.Delegate.Combineメソッドである。これは、System.Delegateクラスの共有メソッドである。ここでSystemというキーワードが必要になるのは、ただDelegateとだけ記述すると、VB.NETのDelegateキーワードとして扱われてしまうためである。このメソッドを使えば、複数のデリゲートを合成した新しいデリゲートを作成できる。つまり、2つのデリゲート・インスタンスが持つ委譲先メソッドのリストが合成され、1つのリストにまとめられる。
このように、複数の委譲先メソッドが合成されたデリゲート・インスタンスを24行目のように呼び出すと、リストに属するすべてのメソッドが呼び出される。複数の処理をまとめて実行させるには便利な機能だが、戻り値を受け取りたい場合は適切ではない。一度にいくつものメソッドを呼び出せるが、受け取れる戻り値は最後に呼ばれたメソッドの戻り値ただ1つだけである。
デリゲートに含まれる委譲先リストは、いつでも追加/削除することができる。追加にSystem.Delegate.Combineメソッドを用いることはすでに述べたが、削除する場合はSystem.Delegate.Removeメソッドを用いる。リスト11-19は、リストの追加と削除を行うサンプル・プログラムである。
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-19 委譲先リストの追加と削除を行うプログラム
|
これを実行すると以下のようになる。
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-20 リスト11-19の実行結果
|
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
|
|
リスト11-21 異なるデリゲート型を委譲先リストに格納して呼び出すプログラム(実行時にエラーとなる)
|
これを実行すると「デリゲートは同じ型でなければなりません」という、ランタイムのエラー・メッセージが出力される。16行目のように、異なるデリゲート型のデリゲート・インスタンスを1つのリストにまとめることはできない。たとえ戻り値と引数が一致していても、である。
『VB6プログラマーのための入門 Visual Basic .NET 独習講座』
本記事は、(株)技術評論社が発行する書籍『VB6 プログラマーのための 入門 Visual Basic .NET 独習講座』から許可を得て転載したものです。
【本連載と書籍の関係について 】
この書籍は、本フォーラムで連載した「連載 プロフェッショナルVB.NETプログラミング」を大幅に加筆修正し、発行されたものです。技術評論社、および著者である川俣晶氏のご好意により、書籍の内容を本フォーラムの連載記事として掲載させていただけることになりました。
→技術評論社の解説ページ
ご注文はこちらから
|
業務アプリInsider 記事ランキング
本日
月間