連載

改訂版
プロフェッショナルVB.NETプログラミング

Chapter 11 デリゲート

株式会社ピーデー 川俣 晶
2004/07/22
Page1 Page2 Page3 Page4


 本記事は、(株)技術評論社が発行する書籍『VB6プログラマーのための入門 Visual Basic .NET 独習講座』の一部分を許可を得て転載したものです。同書籍に関する詳しい情報については、本記事の最後に掲載しています。

委譲先を複数持たせる

 デリゲートのインスタンスは委譲先メソッドに関する情報を含むが、この情報は「リスト」として保持される。つまり、委譲先メソッドは複数指定することもできるというわけである。以下は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つのリストにまとめることはできない。たとえ戻り値と引数が一致していても、である。End of Article

VB6プログラマーのための入門 Visual Basic .NET 独習講座』

 本記事は、(株)技術評論社が発行する書籍『VB6 プログラマーのための 入門 Visual Basic .NET 独習講座』から
許可を得て転載したものです。

【本連載と書籍の関係について 】
 この書籍は、本フォーラムで連載した「連載 プロフェッショナルVB.NETプログラミング」を大幅に加筆修正し、発行されたものです。技術評論社、および著者である川俣晶氏のご好意により、書籍の内容を本フォーラムの連載記事として掲載させていただけることになりました。

技術評論社の解説ページ

ご注文はこちらから
 

 INDEX
  [連載] 改訂版 プロフェッショナルVB.NETプログラミング
  Chapter 11 デリゲート
    1.デリゲートとは何か/2つの異なるメソッドに委譲する
    2.共有メソッドへの委譲/デリゲートはインスタンスを選ぶ/戻り値と引数が合えば委譲できる
    3.継承でも実現できるか?/デリゲートをオブジェクトとして使う/Privateキーワードの付いたメソッドへの委譲
  4.委譲先を複数持たせる/委譲先リストの変更/デリゲート型の同一性
 
「改訂版 プロフェッショナルVB.NETプログラミング 」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH