(如何)绑定/重新绑定方法以使用不同签名的委托?

我是一个c ++开发人员,在c ++中使用了信号和插槽,这对我来说似乎与c#中的委托类似。 我发现自己在寻找“绑定”提供的function时感到很茫然,并且觉得我必须遗漏一些东西。

我觉得像C ++这样的东西应该可以在c#中使用委托。 这里有一些psudo代码,用于我将在c ++中做什么:

Slot someCallback; int foo(int i) { std::cout << "Value: " << i << "\n"; return i; } int main() { int i = 0; Slot someCallback = bind( fun_ptr(foo), i ); ++i; // added to show that late evaluation would be a non-trivial difference int result = someCallback(); assert( result == 0 ); return 0; } 

不幸的是,我无法找到任何关于c#delegates的绑定/重新绑定的引用。 我错过了什么吗? 在c#中有一些根本不同的方法吗?

在C#中我们做这样的事情:

 class Program { static Action Curry(Action 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

接下来,我们声明一个接受Action并返回Action的方法Curry 。 通常, Action是一个委托,它接受类型为T的单个参数并返回void 。 特别是, Foo是一个Action因为它接受一个int类型的参数并返回void 。 至于Curry的返回类型,它被声明为ActionAction是一个委托,它没有参数并返回void

Curry的定义相当有趣。 我们使用lambda表达式定义一个动作,这是一种非常特殊的匿名委托forms。 有效

 () => action(parameter) 

表示void参数映射到在parameter计算的action

最后,在Main我们声明了一个名为curriedAction实例,它是使用参数5Curry应用于Foo的结果。 这bind(fun_ptr(foo), 5)您的C ++示例中的bind(fun_ptr(foo), 5)扮演相同的角色。

最后,我们通过语法curried()调用新形成的委托。 这就像你的例子中的someCallback()

这个花哨的术语是讨好的 。

作为一个更有趣的例子,请考虑以下事项:

 class Program { static Func Curry( Func func, TArg arg1 ) { return arg => func(arg1, arg); } static int Add(int x, int y) { return x + y; } static void Main(string[] args) { Func addFive = Curry(Add, 5); Console.WriteLine(addFive(7)); } } 

这里我们声明一个接受委托的方法CurryFunc接受相同类型TArg两个参数并返回其他类型的值TResultTArg类型的参数并返回一个接受的委托TArg类型的单个参数,返回TResult类型的值( Func )。

然后,作为测试,我们声明一个方法Add ,它接受两个int类型的参数,并返回一个int类型的参数(一个Func )。 然后在Main我们实例化一个名为addFive的新委托,它的作用类似于为其输入参数添加五个的方法。 从而

 Console.WriteLine(addFive(7)); 

在控制台上打印12

请尝试以下方法

 class Example { static void foo(int i) { Console.WriteLine(i); } public static void Main() { Action someCallback = () => foo(5); someCallback(); } } 

或者更接近C ++计数器部分的东西

 class Example { static void foo(int i) { Console.WriteLine(i); } static Action bind(Action action, T value) { return () => action(value); } public static void Main() { Action someCallback = bind(foo, 5); someCallback(); } } 

说明。 这里发生的是我正在通过lambda表达式创建一个新的委托。 lambda是以() =>开头的表达式。 在这种情况下,它创建一个委托,不接受任何参数并且不产生任何值。 它与Action类型兼容。