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