無差別に技術をついばむ鳥

情報処理技術全般を気まぐれにつつくゆるいブログです

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メソッドを使用すれば、 使用しなくなったメソッドを除外できよ。これも覚えておいてね。 じゃあこれでお終い!
別窓 | VB.NET | コメント:0 | トラックバック:0 | ∧top | under∨
<<中の人の徒然草26 | 無差別に技術をついばむ鳥 | C++/CLIをつつく23−デリゲート。貴方を呼ぶからね。>>

この記事のコメント

∧top | under∨

コメントの投稿

 

管理者だけに閲覧
 

この記事のトラックバック

∧top | under∨
| 無差別に技術をついばむ鳥 |