ドリィちゃんから
デリゲートの説明を押し付けられたから解説するピヨ。
デリゲートとは(うんたらかんたら)と説明されるのは眠たいと思うので早速このコードをコピペして実行してみて。
#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メソッドを使用すれば、
使用しなくなったメソッドを除外できよ。これも覚えておいてね。
じゃあこれでお終い!