VB.NETでDelegateを使ってみる

2017 年 4 月 17 日 by Dr.K

前回の記事の中では、スレッド処理をおこない、Delegateを利用してメソッドを呼び出す処理をおこないました。
DelegateについてはC#.NETで見かけることはあったのですが、VB.NETではほとんど利用したことが無かったため、これを機会にDelegateがどのようなものか、どういった場面で使えばよいかを紹介していきたいと思います。

まずはDelegateとは何か、というところから。
◆Delegate Wikipediaより

デリゲートは、オブジェクトへの参照と関数オブジェクトへの参照をペアにして持つものである。
オブジェクト指向プログラミングとしては、メソッドをカプセル化するクラスとも言える。型安全であるという特徴がある。

...私はこれだけ読んでも、意味がよく分かりませんでした。
もう少し読み進めてみると

C++の「メンバ関数を指すポインタ」や、Object Pascal(Delphi)の「インスタンスのメソッドへのポインタを格納する、メソッドポインタ」と同様のものである(DelphiもC#もアンダース・ヘルスバーグによる設計である)。また、Microsoft Visual J++も、Javaと非互換のデリゲートを導入したが、.NET Frameworkのデリゲートはこれらを発展させたものである。

C++は少しかじっていたことがあったので、「関数を指すポインタ」と同様、というところでピンときたのですが、意味合いとしては関数を変数にセットしておき、必要な場面でその変数(=関数)を呼び出し実行する、ようなイメージになると思います。
Delegateがない場合、関数を呼び出すときにはその場で関数を呼び出す記述が必要でしたが、Delegateを利用すれば、処理分岐などのタイミングで関数をセット、後に処理を呼び出す、という使い方もできそうです。

というわけで、簡単なサンプルとして、2つの数値を足し算、または掛け算するWindowsアプリケーションを作成してみます。
以下のような画面を用意しておきます。

ボタンクリック時の処理を実装します。

VB.NET:
  1. Public Class Form1
  2.  
  3.     ' Delegateを宣言
  4.     Delegate Function CalcDelegate(i1 As Integer, i2 As Integer) As Integer
  5.  
  6.     'Delegateで呼び出す足し算を定義
  7.     Private Function CalcAdd(num1 As Integer, num2 As Integer) As Integer
  8.         Return num1 + num2
  9.     End Function
  10.  
  11.     'Delegateで呼び出す掛け算を定義
  12.     Private Function CalcMulti(num1 As Integer, num2 As Integer) As Integer
  13.         Return num1 * num2
  14.     End Function
  15.  
  16.     'ボタンクリックイベント
  17.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  18.         'Delegateを格納する変数を宣言
  19.         Dim dlg As CalcDelegate
  20.         Dim iNum1 As Integer = 0
  21.         Dim iNum2 As Integer = 0
  22.         Dim iResult As Integer = 0
  23.  
  24.         'テキストボックスの入力値を数値として変数にセット
  25.         iNum1 = CInt(Num1.Text)
  26.         iNum2 = CInt(Num2.Text)
  27.  
  28.         'コンボボックスの内容によってどの関数をDelegateにセットするか分岐
  29.         Select Case ComboBox1.Text
  30.             Case "+"
  31.                 '足し算用の関数をDelegateにセット
  32.                 dlg = AddressOf CalcAdd
  33.             Case "×"
  34.                 '掛け算用の関数をDelegateにセット
  35.                 dlg = AddressOf CalcMulti
  36.             Case Else
  37.                 Exit Sub
  38.         End Select
  39.  
  40.         'Delegateを呼び出し
  41.         iResult = dlg(iNum1, iNum2)
  42.  
  43.         'Delegateからの戻り値を結果として表示
  44.         Result.Text = iResult
  45.     End Sub
  46. End Class

このプログラムを実行してみると、以下のような動きになります。
e794bbe5838f2

ポイントとしては、Button1_Clickイベント中のSelect文で、コンボボックスの内容に応じてDelegateの処理内容を分岐させ、全体の造りを共通化しています。
もちろん、今回のようにDelegateから呼び出す関数の引数と戻り値が一致していたからこそ共通化できたわけですが、同じ処理を2種類用意したり、クラスの継承などで共通化したりする必要がない分、Delegateを利用して処理を共通化できる場面は多くなると思います。

今回はDelegateについて、実装の方法と利用場面について紹介しました。
Delegateはイベントの処理などでも利用されているのですが、VB.NETではあまり意識しなくてもイベント処理が実装できてしまいます。
ただVB.NETの仕組みを理解するうえでもDelegateは重要な部分の為、今後も色々な使い方について紹介していければと思います。

タグ:

TrackBack