|   | 
  | 
連載
改訂版 
プロフェッショナルVB.NETプログラミング
Chapter 11 デリゲート  
株式会社ピーデー
川俣 晶 
2004/07/22 | 
 | 
 
 | 
 上記の例を見て、掛け算も足し算も完全に独立した処理であるため、共有メソッド(インスタンスを作成せずに呼び出せるメソッドを参照)にしても何ら問題ないことに気付いた人もいるだろう。では、共有メソッドへの委譲は記述できるのだろうか? 
 リスト11-6は、そのように修正してみたプログラムである。
 1: Delegate Function SampleDelegate(ByVal x As Integer, ByVal y As Integer) As Integer 
 2:  
 3: Public Class SampleClass 
 4:   Public Shared Function MethodMult(ByVal x As Integer, ByVal y As Integer) As Integer 
 5:     Return x * y 
 6:   End Function 
 7:  
 8:   Public Shared Function MethodPlus(ByVal x As Integer, ByVal y As Integer) As Integer 
 9:     Return x + y 
10:   End Function 
11: End Class 
12:  
13: Public Class Form1 
14:   Inherits System.Windows.Forms.Form 
15:  
16: …Windows フォーム デザイナで生成されたコード… 
17:  
18:   Private Sub calc(ByVal x As Integer, ByVal y As Integer, ByVal calcMethod As SampleDelegate) 
19:     Dim result As Integer = calcMethod(x, y) 
20:     Trace.WriteLine(result) 
21:   End Sub 
22:  
23:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
24:     Dim instance As New SampleClass() 
25:     calc(2, 3, AddressOf SampleClass.MethodMult) 
26:     calc(2, 3, AddressOf SampleClass.MethodPlus) 
27:   End Sub 
28: End Class 
 | 
 
 
 | 
 
  
リスト11-6 リスト11-1の委譲先となる2つのメソッドを共有メソッドにしたプログラム
 | 
 これを実行すると以下のようになる。
| 
 | 
 
  
リスト11-7 リスト11-6の実行結果
 | 
 共有メソッドを指定するために、インスタンス名の代わりにクラス名を使用することができる。25行目のSampleClass.MethodMultのようにメソッド名を記述すれば、その共有メソッドが利用可能である。それ以外には特別な記述はなく、デリゲートの宣言や呼び出し時に特別な配慮は必要ないことが分かると思う。
 これは非常に重要なことなので、よく頭に刻み込んでほしいところなのだが、共有メソッドを使う場合を除き、デリゲートはインスタンスとメソッドの情報を扱う。つまり、デリゲートが委譲する先は、ただ単に指定されたメソッドが呼ばれるだけでなく、呼び出し時にどのインスタンスかも明示される。リスト11-8は、複数インスタンスのメソッドを委譲先として使用したサンプル・プログラムである。
 1: Delegate Function SampleDelegate(ByVal x As Integer, ByVal y As Integer) As Integer 
 2:  
 3: Public Class SampleClass 
 4:   Public result As Integer 
 5:   Public Function SampleMethod(ByVal x As Integer, ByVal y As Integer) As Integer 
 6:     result = x * y 
 7:   End Function 
 8: End Class 
 9:  
10: Public Class Form1 
11:   Inherits System.Windows.Forms.Form 
12:  
13: …Windows フォーム デザイナで生成されたコード… 
14:  
15:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
16:     Dim instance1 As New SampleClass() 
17:     Dim instance2 As New SampleClass() 
18:     Dim d1 As SampleDelegate = AddressOf instance1.SampleMethod 
19:     Dim d2 As SampleDelegate = AddressOf instance2.SampleMethod 
20:     d1(2, 3) 
21:     d2(4, 5) 
22:     Trace.WriteLine(instance1.result) 
23:     Trace.WriteLine(instance2.result) 
24:   End Sub 
25: End Class 
 | 
 
 
 | 
 
  
リスト11-8 2つの異なるインスタンスのデリゲートを呼び出すプログラム
 | 
 これを実行すると以下のようになる。
| 
 | 
 
  
リスト11-9 リスト11-8の実行結果
 | 
 ここでは、同じSampleClassクラスのインスタンスを2つ作成している(16〜17行目)。この2つのインスタンスに対して、別々にデリゲート・インスタンスを作成している(18〜19行目)。
 さて、ここからがこのサンプル・プログラム最大の注目点だ。20〜21行目のメソッド呼び出しには、どのSampleClassインスタンスを対象にするか、明示的には表現されていない。しかし、デリゲート・インスタンスは、どのSampleClassインスタンスを対象とするかを覚えているので、間違いなく、18〜19行目で指定されたSampleClassインスタンスのメソッドを呼び出す。
 このように、デリゲートはメソッドだけでなく、インスタンスも識別することをよく覚えておいていただきたい。特に、C/C++の関数ポインタをご存じの方は注意が必要である。関数ポインタは関数を特定する機能しか持たず、インスタンスを特定する情報は持たないのである。
 デリゲートは、対象となるメソッドにPrivateキーワードなどが付加されてアクセス権が与えられていない場合などを除き、戻り値と引数が合えば委譲できる。別クラスの異なる名前のメソッドであっても、戻り値と引数だけ合っていれば委譲できる。リスト11-9は、まったく無関係な別クラスの異なる名前のメソッドに委譲した例である。
 1: Delegate Function SampleDelegate(ByVal x As Integer, ByVal y As Integer) As Integer 
 2:  
 3: Public Class SampleClass1 
 4:   Public result As Integer 
 5:   Public Function MethodMult(ByVal x As Integer, ByVal y As Integer) As Integer 
 6:     result = x * y 
 7:   End Function 
 8: End Class 
 9:  
10: Public Class SampleClass2 
11:   Public result As Integer 
12:   Public Function MethodPlus(ByVal x As Integer, ByVal y As Integer) As Integer 
13:     result = x + y 
14:   End Function 
15: End Class 
16:  
17: Public Class Form1 
18:   Inherits System.Windows.Forms.Form 
19:  
20: …Windows フォーム デザイナで生成されたコード… 
21:  
22:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
23:     Dim instance1 As New SampleClass1() 
24:     Dim instance2 As New SampleClass2() 
25:     Dim d1 As SampleDelegate = AddressOf instance1.MethodMult 
26:     Dim d2 As SampleDelegate = AddressOf instance2.MethodPlus 
27:     d1(2, 3) 
28:     d2(4, 5) 
29:     Trace.WriteLine(instance1.result) 
30:     Trace.WriteLine(instance2.result) 
31:   End Sub 
32: End Class 
 | 
 
 
 | 
 
  
リスト11-9 無関係なクラスの異なる名前のメソッドに委譲するプログラム
 | 
 これを実行すると以下のようになる。
| 
 | 
 
  
リスト11-10 リスト11-9の実行結果
 | 
 このように、デリゲートの対象となるメソッドは、クラスの種類やメソッド名などには制限されない。
 
 
	
		業務アプリInsider 記事ランキング
		
		
			本日
			月間