まさにそのような目的のために、Microsoft は.NET フレームワークでActionおよびFuncラッパー クラスを作成しました。どちらのクラスも無名関数に依存しています。匿名関数を実行するためだけに、結果を返す必要がない場合は Action を使用します。
private void DoSomething(Action action)
{
action();
}
次のように使用できます。
DoSomething(() =>
{
Console.WriteLine("test");
});
この() =>
用語はラムダ式で、 のようなものを意味しますinput with no parameters is calling ...
。詳細な説明については、ドキュメントを参照してください。
結果を返したい場合は、 Func デリゲートを使用します。
private T DoSomething<T>(Func<T> actionWithResult)
{
return actionWithResult();
}
使用法:
Console.WriteLine(DoSomething<int>(() =>
{
return 100;
}));
両方のラッパーには、最大 8 つのパラメーターを受け入れるオーバーライドがあります。
Func を使用する場合、最後のパラメーターは常に戻り値の型です。
// returns a string
Func<string> t = () => { return "test string"; };
// first parameter is of type int, result of type string
Func<int, string> toString = (id) => { return id.ToString(); };
// parameters are of type int and float, result is string
Func<int, float, string> sumToString = (n1, n2) => { return (n1 + n2).ToString(); };
Func ラッパーは、型付きパラメーターで直接使用できます。
Func<string, string> up = text => text.ToUpper();
Console.WriteLine(up("test"));
私はよく Func を使用して、try/catch ブロックにラップされ、何かが発生した場合にログを記録する汎用エグゼキューターを作成します。このようにして、繰り返しコードを減らします。
private T safeCallWithLog<T>(Func<T> action)
{
try
{
return action();
}
catch (Exception ex)
{
Console.WriteLine(String.Format("Oops ...: {0}", ex.Message));
}
// return default type if an error occured
return default(T);
}
使用法:
var result = safeCallWithLog<DbEntry>(() =>
{
return databaseContext.GetEntryWithId(42);
});
var id = safeCallWithLog<int>(() =>
{
return databaseContext.GetIdFor("J.D.");
});
元のデリゲートの概念を引き続き使用できます。Action クラスと Func クラスは、定義済みのジェネリック デリゲート メソッドの単なるラッパーです。
// declare delegate contract
private delegate void output();
// create caller method
private void method(output fun)
{
fun();
}
// some test functions, that must match exactly the delegate description
// return type and number of arguments
private void test1()
{
Console.WriteLine("1");
}
private void test2()
{
Console.WriteLine(DateTime.Now.ToString());
}
// call different methods
method(test1);
method(test2);
// inline call without hard coded method
method(delegate()
{
Console.WriteLine("inline");
});