可変引数なActionとかFuncとか

 C#2.0以降で、ActionやFuncというメソッドをカプセル化するデリゲートが標準で提供され、C#3.0以降にサポートされたラムダ式で更に使うようになった。で、ジェネリックタイプのAction<>でサポートされている引数の数は、最大で14個。まあ、これを超える引数を使うなんて事はそうそうない。でも、例えば、同じ型のインスタンスを任意の数で引数にしたい。そう、可変長引数的な使い方はできないものか?とちょっと思った。
 そもそも、そういう需要はあるのか?とか思うんだけども。一応そういう時が来る時の為の備忘録としてメモっておく。
※オリジナルではなく、以下の書籍で見つけた内容。

C#クックブック 第3版C#クックブック 第3版
(2008/08/25)
Jay Hilyard、Stephen Teilhet 他

商品詳細を見る

○デリゲートを自前で定義
 ActionやFuncで、Genericな定義がなかった頃にもやったなぁ。
public delegate void ActionOptional<T>(params T[] args);
名前はなんでも良いけど、できるだけ思い出しやすいように近い名前にしておく。

○使い方。
ActionOptional<int> action = args => {
//argsは、int配列として扱えます。
if (args == null || args.Length == 0) {
return;
}

foreach (var val in args) {
//何かしらの処理
}
return;
};

//基本、何個だろうと、↑の定義で済ませられる。
action(1);
action(1, 2, 3);
action(1, 2, 3, 4);
action(1, 2, 3, 4, 5);
定義はしてみたけど、仕事でいざ使おうと思うと、これが意外に機会がなかったりする。集計値や平均値等は、元々その計算対象となるデータは元々配列で与えられるし、任意の数だとしても、上記のようなコーディングはまずない。そもそも、集計値や平均値、最大値等は、その結果として返すべき値を持つので、Actionではなく、Funcなんだろうなと。
・同じタイプを返す、可変引数Func
public delegate T FuncOptional<T>(params T[] args);

・別のタイプを返す、可変引数Func
public delegate S FuncOptional<T, S>(params T[] args);

このFuncOptionalなら、クロージャという形で何かしらの機能をカプセル化して提供しても良いかもしれない。
using System;

namespace TawamureDays {

/// <summary>可変引数Func(戻り値も同タイプ)</summary>
public delegate T FuncOptional<T>(params T[] args);

public static partial class Utils {

/// <summary>
/// 引数値を初期値とした任意の個数を受け取って、積算して返す
/// クロージャを取得します。<br/>
/// </summary>
/// <param name="start">初期値</param>
/// <returns>任意個数の引数を積算するクロージャ</returns>
public static FuncOptional<int> Total(int start = 0) {
var current = start;

FuncOptional<int> sigma = valsList => {

if (Utils.IsNullOrEmpty(valsList)) {
return current;
}

foreach (var element in valsList) {
current += element;
}

return current;
};

return sigma;
}
}
}


○使い方
var total = Utils.Total(0);
var val = total(1, 2, 3);//val = 6
val = total(4, 5);//val=16

うん、まあ、例が悪いだけで、使い道はある…と思いたいな。
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: C# | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m