|   | 
  | 
連載
改訂版 
プロフェッショナル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 記事ランキング
		
		
			本日
			月間