我是一名 C++ 开发人员,在 C++ 中使用过信号和槽,这对我来说似乎类似于 C# 中的委托(delegate)。我发现自己在寻找“绑定(bind)”提供的功能时不知所措,觉得我一定遗漏了一些东西。
我觉得像下面这样的东西,在 c++ 中是可能的,在带有委托(delegate)的 c# 中应该是可能的。这是我在 C++ 中所做的一些伪代码:
Slot<void> someCallback;
int foo(int i)
{
std::cout << "Value: " << i << "\n";
return i;
}
int main()
{
int i = 0;
Slot<int> 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# 委托(delegate)的绑定(bind)/重新绑定(bind)引用。我错过了什么吗?在 C# 中是否有一些完全不同的方法来做到这一点?
最佳答案
在 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
。通常, Action<T>
是一个接受类型为 T
的单个参数并返回 void
的委托(delegate)。特别地, Foo
是一个 Action<int>
因为它接受一个类型为 int
的参数并返回 void
。至于 Curry
的返回类型,它被声明为 Action
。 Action
是一个没有参数并返回 void
的委托(delegate)。
Curry
的定义比较有趣。我们正在使用 lambda 表达式定义一个操作,这是一种非常特殊的匿名委托(delegate)形式。有效
() => action(parameter)
表示 void
参数映射到 action
,在 parameter
处求值。
最后,在 Main
中,我们声明了一个名为 Action
的 curried
实例,它是使用参数 Curry
将 Foo
应用于 5
的结果。这与您的 C++ 示例中的 bind(fun_ptr(foo), 5)
起着相同的作用。
最后,我们通过语法 curried
调用新形成的委托(delegate) 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
接受一个委托(delegate)( Func<TArg, TArg, TResult>
接受两个相同类型的参数 TArg
并返回一些其他类型的值 TResult
和一个类型为 TArg
的参数并返回一个接受单个参数的委托(delegate)键入 TArg
并返回类型为 TResult
( Func<TArg, TResult>
) 的值。
然后,作为测试,我们声明一个方法 Add
,它接受两个类型为 int
的参数并返回一个类型为 int
的参数(一个 Func<int, int, int>
)。然后在 Main
中,我们实例化一个名为 addFive
的新委托(delegate),它的作用类似于将输入参数加 5 的方法。因此
Console.WriteLine(addFive(7));
在控制台上打印 12
。
关于c# - (如何)是否可以绑定(bind)/重新绑定(bind)一个方法来与不同签名的委托(delegate)一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2098322/