C#では、次のようなことを行います。
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
。一般に、anAction<T>
は、型の単一のパラメーターを受け取り、T
を返すデリゲートですvoid
。特に、Foo
は、Action<int>
型の1つのパラメーターを受け入れint
、を返すためvoid
です。の戻り型についてはCurry
、として宣言されていAction
ます。AnAction
はデリゲートであり、パラメータがなく、を返しますvoid
。
の定義Curry
はかなり興味深いものです。匿名デリゲートの非常に特殊な形式であるラムダ式を使用してアクションを定義しています。効果的に
() => action(parameter)
パラメータがで評価void
されるようにマップされていることを示します。action
parameter
最後に、パラメータを使用してに適用した結果であるnamedMain
のインスタンスを宣言しています。これは、 C++の例と同じ役割を果たします。Action
curried
Curry
Foo
5
bind(fun_ptr(foo), 5)
curried
最後に、構文を介して新しく形成されたデリゲートを呼び出しますcurried()
。これはsomeCallback()
あなたの例のようです。
これの派手な用語はカリー化です。
より興味深い例として、次のことを考慮してください。
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>
同じタイプの2つのパラメーターを受け入れ、TArg
他のタイプの値とTResult
タイプのパラメーターをTArg
返し、タイプの単一のパラメーターを受け入れ、タイプTArg
の値を返すデリゲートを返しますTResult
(Func<TArg, TResult>
)。
次に、テストとして、Add
型の2つのパラメーターを受け取り、型(a )int
のパラメーターを返すメソッドを宣言します。次に、入力パラメーターに5を追加するメソッドのように機能するという名前の新しいデリゲートをインスタンス化します。したがってint
Func<int, int, int>
Main
addFive
Console.WriteLine(addFive(7));
12
コンソールに印刷します。