C++/CLIをつつく23-デリゲート。貴方を呼ぶからね。
#include "stdafx.h"
using namespace System;
ref class Program
{
private:
//デリゲートの宣言だピヨ
delegate Double SimpleComputer( Byte val, Byte val1 );
static Double Add( Byte val, Byte val1 ) {
Double rval = val + val1;
Console::Write( "{0}と{1}の足し算を行います。", val, val1 );
Console::Write( "答えは【{0}】です。\n", rval );
return rval;
}
static Double Subtract( Byte val, Byte val1 ) {
Double rval = val - val1;
Console::Write( "{0}と{1}の引き算を行います。", val, val1 );
Console::Write( "答えは【{0}】です。\n", rval );
return rval;
}
static Double Multiply( Byte val, Byte val1 ) {
Double rval = val * val1;
Console::Write( "{0}と{1}の掛け算を行います。", val, val1 );
Console::Write( "答えは【{0}】です。\n", rval );
return rval;
}
static Double Divide( Byte val, Byte val1 ) {
Double rval = (Double)val / (Double)val1;
Console::Write( "{0}と{1}の割り算を行います。", val, val1 );
Console::Write( "答えは【{0}】です。\n", rval );
return rval;
}
//ここでデリゲートを有効利用しているピヨ
static void Calculate( Byte val, Byte val1, SimpleComputer^ function ) {
if(function != nullptr) {
function( val, val1 );
}
}
public:
static void SingleExe( ) {
Console::WriteLine( "********************"
"一つずつメソッドを呼び出して計算します********************" );
Random^ ran = gcnew Random( ( Int32 ) DateTime::Now.Ticks );
Byte val = ( Byte ) ran->Next( 1, 100 );
Byte val1 = ( Byte ) ran->Next( 1, 100 );
Calculate( val, val1, gcnew SimpleComputer(&Program::Add) );
val = ( Byte ) ran->Next( 1, 100 );
val1 = ( Byte ) ran->Next( 1, 100 );
Calculate( val, val1, gcnew SimpleComputer(&Program::Subtract) );
val = ( Byte ) ran->Next( 1, 100 );
val1 = ( Byte ) ran->Next( 1, 100 );
Calculate( val, val1, gcnew SimpleComputer(&Program::Multiply) );
val = ( Byte ) ran->Next( 1, 100 );
val1 = ( Byte ) ran->Next( 1, 100 );
Calculate( val, val1, gcnew SimpleComputer(&Program::Divide) );
Console::WriteLine( "");
}
static void MultiExe( ) {
Console::WriteLine( "********************" +
"一度にメソッド呼び出して計算します********************" );
SimpleComputer^ add = gcnew SimpleComputer( Add );
SimpleComputer^ sub = gcnew SimpleComputer( Subtract );
SimpleComputer^ mul = gcnew SimpleComputer( Multiply );
SimpleComputer^ div = gcnew SimpleComputer( Divide );
SimpleComputer^ all = nullptr;
all = ( SimpleComputer^ ) Delegate::Combine( all, add );
all = ( SimpleComputer^ ) Delegate::Combine( all, sub );
all = ( SimpleComputer^ ) Delegate::Combine( all, mul );
all = ( SimpleComputer^ ) Delegate::Combine( all, div );
Random^ ran = gcnew Random( ( Byte ) DateTime::Now.Ticks );
Byte val = ( Byte ) ran->Next( 1, 100 );
Byte val1 = ( Byte ) ran->Next( 1, 100 );
Calculate( val, val1, all );
Console::WriteLine( "" );
Console::WriteLine( "********************" +
"割り算以外を計算します********************" );
all = ( SimpleComputer^ ) Delegate::Remove( all, div );
val = ( Byte ) ran->Next( 1, 100 );
val1 = ( Byte ) ran->Next( 1, 100 );
Calculate( val, val1, all );
Console::WriteLine( "" );
}
};
int main(array< System::String ^> ^args)
{
Program::SingleExe( );
Program::MultiExe( );
return 0;
}
ちょっと長いけど勘弁してね。どう?実行した?面白い動きをするでしょ?ピヨ?ピヨ?
でも一応解説して欲しいと思うから一つずつ解説するッピヨ。
まずはデリゲートの宣言を見てみよう。
delegate Double SimpleComputer( Byte val, Byte val1 );何かメソッドの定義みたいだね。と思った貴方は鋭い!。 デリゲートの宣言はメソッドの定義を決めるのに等しいピヨ。 このサンプルコードの場合は、Double型の値を返す、二つのByte型の値を受け取るメソッド を表しているんだ。これが何を意味するかは、これから解説するピヨ。
次に注目するべきなのは、Calculateメソッドピヨォ。 三つ目の引数にSimpleComputerデリゲートを受け取っているよね。 それの使い方を見て。メソッドの呼び出しそのものピヨ。 だからボクはさっきメソッドの定義に等しいと表現したんだ。
今のところデリゲートは単純そうに見えるんだけど、 デリゲートの機能は単純にメソッドを呼び出すだけではないんだ。 なんと!一度に複数のメソッドを一気に呼び出せるんだ。全て同じ値で計算されているからそれが分かるピヨ。 MultiExeメソッド内の処理を見てごらん。
Calculate( val, val1, all );を一回しか呼んでいないピヨ。 でもちゃんと全部メソッドを呼んでいるよね。どう?不思議だよね。 これにはちゃんとしたトリックがあるんだ。そのトリックは、 Delegate.Invokeメソッドさ。 このメソッドは暗黙的に使用されてstrong>一つのデリゲート内に複数のメソッドを格納できるんだ。 だから一回呼べば全て呼ばれるんだ。これを応用すれば面白いソフトが作れるよ。色々妄想すると楽しいピヨ。 勿論、逆の処理も可能で、Delegate.Removeメソッドを使用すれば、 使用しなくなったメソッドを除外できよ。これも覚えておいてね。 じゃあこれでお終い!