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

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

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

この記事のコメント

複数のdelegateをまとめて呼べるようにするのは Delegateメソッドじゃありません。
2009-04-04 Sat 10:19 | URL | επιστημη #-[ 内容変更]
> 複数のdelegateをまとめて呼べるようにするのは Delegateメソッドじゃありません。

助かります♪
流石επιστημη さんです。
これは、Delegate型のInvokeメソッドの記入漏れです。
今すぐ修正します。
2009-04-04 Sat 10:30 | URL | インドリ #-[ 内容変更]
もうひとつ。

× デリゲートの宣言はメソッドの定義を決めるのに等しい
○ デリゲートの宣言はメソッドのシグニチャ(引数の型と数および戻り値の型)を決めるのに等しい
2009-05-10 Sun 01:35 | URL | επιστημη #-[ 内容変更]
∧top | under∨

コメントの投稿

 

管理者だけに閲覧
 

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

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