VB.NETをつつく23-デリゲート。貴方達を呼びつけるからね。
Imports System
Public Class Program
Private Delegate Function SimpleComputer( _
ByVal val As Byte, ByVal val1 As Byte) As Double
Private Shared Function Add( _
ByVal val As Byte, ByVal val1 As Byte) As Double
Dim rval As Double = CType(val, Double) + CType(val1, Double)
Console.Write("{0}と{1}の足し算を行います。", val, val1)
Console.Write("答えは【{0}】です。" & vbLf, rval)
Return rval
End Function
Private Shared Function Subtract( _
ByVal val As Byte, ByVal val1 As Byte) As Double
Dim rval As Double = CType(val, Double) - CType(val1, Double)
Console.Write("{0}と{1}の引き算を行います。", val, val1)
Console.Write("答えは【{0}】です。" & vbLf, rval)
Return rval
End Function
Private Shared Function Multiply( _
ByVal val As Byte, ByVal val1 As Byte) As Double
Dim rval As Double = CType(val, Double) * CType(val1, Double)
Console.Write("{0}と{1}の掛け算を行います。", val, val1)
Console.Write("答えは【{0}】です。" & vbLf, rval)
Return rval
End Function
Private Shared Function Divide( _
ByVal val As Byte, ByVal val1 As Byte) As Double
Dim rval As Double = CType(val, Double) / CType(val1, Double)
Console.Write("{0}と{1}の割り算を行います。", val, val1)
Console.Write("答えは【{0}】です。" & vbLf, rval)
Return rval
End Function
Private Shared Function Calculate( _
ByVal val As Byte, ByVal val1 As Byte, ByRef fun As SimpleComputer) _
As Double
fun(val, val1)
End Function
Private Shared Sub SingleExe()
Console.WriteLine("********************" & _
"一つずつメソッドを呼び出して計算します********************")
Dim ran As Random = New Random( _
CType(Math.Min(DateTime.Now.Ticks, Integer.MaxValue), Integer))
Dim val As Byte = CByte(ran.Next(1, 100))
Dim val1 As Byte = CByte(ran.Next(1, 100))
Calculate(Val, val1, AddressOf Add)
val = CByte(ran.Next(1, 100))
val1 = CByte(ran.Next(1, 100))
Calculate(Val, val1, AddressOf Subtract)
val = CByte(ran.Next(1, 100))
val1 = CByte(ran.Next(1, 100))
Calculate(Val, val1, AddressOf Multiply)
val = CByte(ran.Next(1, 100))
val1 = CByte(ran.Next(1, 100))
Calculate(Val, val1, AddressOf Divide)
Console.WriteLine("")
End Sub
Private Shared Sub MultiExe()
Console.WriteLine("********************" & _
"一度にメソッド呼び出して計算します********************")
Dim addfun As SimpleComputer = New SimpleComputer(AddressOf Add)
Dim subfun As SimpleComputer = New SimpleComputer(AddressOf Subtract)
Dim mulfun As SimpleComputer = New SimpleComputer(AddressOf Multiply)
Dim divfun As SimpleComputer = New SimpleComputer(AddressOf Divide)
Dim allfun As SimpleComputer = Nothing
allfun = CType(System.Delegate.Combine(allfun, addfun), SimpleComputer)
allfun = CType(System.Delegate.Combine(allfun, subfun), SimpleComputer)
allfun = CType(System.Delegate.Combine(allfun, mulfun), SimpleComputer)
allfun = CType(System.Delegate.Combine(allfun, divfun), SimpleComputer)
Dim ran As Random = New Random( _
CInt(Math.Min(DateTime.Now.Ticks, Integer.MaxValue)))
Dim val As Byte = CByte(ran.Next(1, 100))
Dim val1 As Byte = CByte(ran.Next(1, 100))
Calculate(val, val1, allfun)
Console.WriteLine("")
Console.WriteLine("********************" & _
"割り算以外を計算します********************")
allfun = CType(System.Delegate.Remove(allfun, divfun), SimpleComputer)
val = CByte(ran.Next(1, 100))
val1 = CByte(ran.Next(1, 100))
Calculate(val, val1, allfun)
Console.WriteLine("")
End Sub
Shared Sub Main()
SingleExe()
MultiExe()
End Sub
End Class
ちょっと長いけど勘弁してね。どう?実行した?面白い動きをするでしょ?ピヨ?ピヨ?
でも一応解説して欲しいと思うから一つずつ解説するッピヨ。
まずはデリゲートの宣言を見てみよう。
Private Delegate Function SimpleComputer( _ ByVal val As Byte, ByVal val1 As Byte) As Double何かメソッドの定義みたいだね。と思った貴方は鋭い!。 デリゲートの宣言はメソッドの定義を決めるのに等しいピヨ。 このサンプルコードの場合は、Double型の値を返す、二つのByte型の値を受け取るメソッド を表しているんだ。これが何を意味するかは、これから解説するピヨ。
次に注目するべきなのは、Calculateメソッドピヨォ。 三つ目の引数にSimpleComputerデリゲートを受け取っているよね。 それの使い方を見て。メソッドの呼び出しそのものピヨ。 だからボクはさっきメソッドの定義に等しいと表現したんだ。
今のところデリゲートは単純そうに見えるんだけど、 デリゲートの機能は単純にメソッドを呼び出すだけではないんだ。 なんと!一度に複数のメソッドを一気に呼び出せるんだ。全て同じ値で計算されているからそれが分かるピヨ。 MultiExeメソッド内の処理を見てごらん。
Calculate( val, val1, allfun )が一回しか呼んでいないピヨ。 でもちゃんと全部メソッドを呼んでいるよね。どう?不思議だよね。 これにはちゃんとしたトリックがあるんだ。そのトリックは、 Delegate.Invokeメソッドさ。 このメソッドが暗黙的に使用されて一つのデリゲート内に複数のメソッドを格納できるんだ。 だから一回呼べば全て呼ばれるんだ。これを応用すれば面白いソフトが作れるよ。色々妄想すると楽しいピヨ。 勿論、逆の処理も可能で、Delegate.Removeメソッドを使用すれば、 使用しなくなったメソッドを除外できよ。これも覚えておいてね。 じゃあこれでお終い!