3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(.Net)ジェネリックデリゲート(汎用デリゲート)を使ってみた

(.Net)デリゲートを自作するメリットがようやく分かってきたで、デリゲートの使い方を書きました。

しかし、delegate型の変数を定義しないといけません。

それを簡略化できる定義済みデリゲート(ジェネリックデリゲート)型というものが.Net Framework2.0以降から存在します。

.Net 2.0では Action(T obj) というデリゲート型が用意されています。

ただし、戻り値は void で、引数は1つという制約が有ります。

.Net 3.5ではさらに定義済みデリゲートが強化され、戻り値を返さない Action デリゲート型が引数なしから引数4つまでに対応、また、Func デリゲートという戻り値を返すデリゲート型も実装されました。

使うことができる定義済みデリゲート型の詳細については、@IT:汎用的に使用できる定義済みのデリゲート型は?[C#、VB]に一覧が載っています。

実際に Action デリゲート型を使ってみた例です。(C# .Net 2.0仕様)

.Net Framework2.0 仕様にしているので、メソッドに複数の引数を渡したいときは、クラスでラップしてます。

public partial class Form1 : Form{

//ボタン押下時

private void button6_Click(object sender, EventArgs e){

//Acitonデリゲート型変数に戻り値無しのCalcAddition3メソッドを関連付け

Action act = CalcAddition3;

Calc3(act, 5,10);

}

//ボタン押下時

private void button7_Click(object sender, EventArgs e){

//Acitonデリゲート型変数に戻り値無しのCalcAddition3メソッドを関連付け

Action act = CalcSubtraction3;

Calc3(act, 5,10);

}

///

デリゲート経由で呼び出される。

private void CalcAddition3(RapObj act){

Console.WriteLine(act.X + act.Y);

}

///

デリゲート経由で呼び出される。

private void CalcSubtraction3(RapObj act){

Console.WriteLine(act.X - act.Y);

}

private void Calc3(Action act, int x,int y) {

try{

 

//いろいろな共通処理...

//共通処理の例としてxとyをインクリメントする

x++; y++;

//.Net 2.0 のActionデリゲートは引数が1個しかとれないのでクラスでラッピング。

RapObj obj = new RapObj();

obj.X = x; obj.Y = y;

//デリゲート経由のメソッド呼び出し

act(obj);

//いろいろな共通処理...

}catch {

//本来はここに例外処理を実装

}

}

}

 

//Actionデリゲートが一つしか引数取れないので、複数に対応できるようこのクラスでラッピング

public class RapObj{

private int iX;

private int iY;

public int X {

get { return iX; }

set { this.iX = value; }

}

public int Y {

get { return iY; }

set { this.iY = value; }

}

}

.Net3.5 で戻り値を返す Func デリゲートを使った例は下記のようになります。(C# .Net3.5以上)

int型引数を二つとり、long型を返すメソッドを呼び出す例です。

//ボタン押下時

private void button7_Click(object sender, EventArgs e){

//Funcデリゲート型変数に戻り値有りのCalcAdditionメソッドを関連付(引数1の型,引数2の型,戻り値の型)

Funcint, long> fnc = CalcAddition;

Calc4(fnc, 10, 5);

}

//ボタン押下時

private void button8_Click(object sender, EventArgs e){

//Funcデリゲート型変数に戻り値有りのCalcAdditionメソッドを関連付(引数1の型,引数2の型,戻り値の型)

Funcint, long> fnc = CalcSubtraction;

Calc4(fnc, 10, 5);

}

 

///

計算(足し算)だけ行う。デリゲート経由で呼び出される。

private long CalcAddition(int x, int y) {

return x + y;

}

///

計算(引き算)だけ行う。デリゲート経由で呼び出される。

private long CalcSubtraction(int x, int y) {

return x - y;

}

 

private void Calc4(Funcint,long> fnc, int x, int y){

try {

//いろいろな共通処理...

//共通処理の例としてxとyをインクリメントする

x++; y++;

long res = fnc(x, y);

Console.WriteLine("計算結果:" + res);

//いろいろな共通処理...

} catch {

//本来はここに例外処理を実装

}

}

こうみると、引数が0から4まで使える .Net 3.5 以降の定義済みデリゲートは使い道が結構ありそうですね。

ただし、やはりデリゲートを経由してメソッドを呼び出す場合、それらのメソッドの引数、戻りの型が一致してないとダメというのがちょっと使いづらいです。

参考:

IT.NET C# - Action デリゲートを扱うには... (1)

IT.NET C# - Action デリゲートを扱うには... (2)

IT.NET C# - Action デリゲートを扱うには... (3)

ジェネリックなメソッドやデリゲートがもたらす新スタイル - @IT

FuncデリゲートとActionデリゲート - c_sharpの日記

Action<T>を使い倒してみる - パジャマdeブロッガー(myugaruのヲタ日記)

【C#】Action / Func デリゲート - プログラム & 語学 の個人的なメモ - Yahoo!ブログ