Ответ 1
Именно для таких целей Microsoft создала Действие и Func оболочки в среде .NET. Оба класса полагаются на анонимные функции. Используйте действие, если вам не нужно возвращать какой-либо результат, просто для выполнения анонимной функции:
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");
});