Ответ 1
В С# мы делаем что-то вроде этого:
class Program {
static Action Curry<T>(Action<T> action, T parameter) {
return () => action(parameter);
}
static void Foo(int i) {
Console.WriteLine("Value: {0}", i);
}
static void Main(string[] args) {
Action curried = Curry(Foo, 5);
curried();
}
}
Очевидно, что метод Foo
соответствует вашему методу Foo
, только с соответствующими вызовами Console.WriteLine
вместо std::cout
.
Затем мы объявляем метод Curry
, который принимает Action<T>
и возвращает Action
. В общем случае Action<T>
является делегатом, который принимает единственный параметр типа T
и возвращает void
. В частности, Foo
является Action<int>
, потому что он принимает один параметр типа int
и возвращает void
. Что касается типа возврата Curry
, он объявляется как Action
. Action
является делегатом, у которого нет параметров и возвращается void
.
Определение Curry
довольно интересно. Мы определяем действие с использованием выражения лямбда, которое является особой формой анонимного делегата. Эффективно
() => action(parameter)
говорит, что параметр void
отображается на Action
, оцененный в parameter
.
Наконец, в Main
мы объявляем экземпляр Action
с именем curried
, который является результатом применения Curry
to Foo
с параметром 5
. Это играет ту же роль, что и bind(fun_ptr(foo), 5)
в вашем примере на С++.
Наконец, мы вызываем новообразованного делегата curried
через синтаксис curried()
. Это как someCallback()
в вашем примере.
Примером этого является currying.
В качестве более интересного примера рассмотрим следующее:
class Program {
static Func<TArg, TResult> Curry<TArg, TResult>(
Func<TArg, TArg, TResult> func,
TArg arg1
) {
return arg => func(arg1, arg);
}
static int Add(int x, int y) {
return x + y;
}
static void Main(string[] args) {
Func<int, int> addFive = Curry<int, int>(Add, 5);
Console.WriteLine(addFive(7));
}
}
Здесь мы объявляем метод Curry
, который принимает делегат (Func<TArg, TArg, TResult>
, который принимает два параметра одного и того же типа TArg
и возвращает значение некоторого другого типа TResult
и параметр типа TArg
и возвращает делегат, который принимает единственный параметр типа TArg
и возвращает значение типа TResult
(Func<TArg, TResult>
).
Затем в качестве теста мы объявляем метод Add
, который принимает два параметра типа int
и возвращает параметр типа int
(a Func<int, int, int>
). Затем в Main
мы создаем новый делегат с именем addFive
, который действует как метод, который добавляет пять к его входному параметру. Таким образом,
Console.WriteLine(addFive(7));
выводит 12
на консоль.