(如何)可以绑定/重新绑定一个方法来处理不同签名的代理? [英] (How) is it possible to bind/rebind a method to work with a delegate of a different signature?
问题描述
我觉得像以下这样的东西,这在c ++中是可能的,在c#中应该是可以的。以下是我在c ++中做的一些psudo代码:
Slot< void>一些
int foo(int i)
{
std :: cout<<< 值:<< i< \\\
;
return i;
}
int main()
{
int i = 0;
Slot< int> someCallback = bind(fun_ptr(foo),i);
++ i; //添加显示后期评估将是一个非平凡的差异
int result = someCallback();
assert(result == 0);
return 0;
}
不幸的是,我没有找到任何参考绑定/重新绑定关于c#代表。我错过了什么吗?在c#中有一些截然不同的方法吗?
在C#中,我们做了这样的事情:
class Program {
static Action Curry< T>(Action< T> action,T参数){
return =>动作(参数);
}
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
的定义非常有趣。我们使用lambda表达式定义一个动作,这是一个非常特殊形式的匿名委托。有效地
()=> action(参数)
说 void
参数被映射到动作
在参数
中进行评估。
最后,在 Main
中,我们正在声明一个 Action的实例
命名为 curried
这是将 Curry
应用于 Foo
与参数 5
。这在C ++示例中起着 bind(fun_ptr(foo),5)
的作用。
最后,我们通过语法 curried()
调用新形成的委托人 curried
。这就像你的例子中的 someCallback()
。
这个花哨的术语是 currying 。
作为一个更有趣的例子,考虑以下几点:
class Program {
static Func< TArg,TResult>咖喱< 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>
)。
然后,作为测试,我们声明一个方法添加
接受两个类型为 int
的参数,并返回一个参数类型为 int
(a Func< int,int,int>
)然后在 Main
中,我们实例化一个名为 addFive
的行为就像一个添加五个输入参数的方法,因此
Console.WriteLine(addFive(7) );
打印 12
在c鞋底。
I'm a c++ developer having used signals & slots in c++ which to me seems to be analogous to delegates in c#. I've found myself at a loss in searching for the functionality provided by "bind", and feel I must be missing something.
I feel like that something like the following, which is possible in c++ should be possible in c# with delegates. Here is some psudo-code for what I would do in 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;
}
Unfortunately, I've not been able to find any reference to binding/rebinding with regards to c# delegates. Am I missing something? Is there some radically different way to do this in c#?
In C# we do something like this:
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();
}
}
Clearly the method Foo
corresponds to your method Foo
, just with the appropriate calls to Console.WriteLine
instead of std::cout
.
Next, we declare a method Curry
that accepts an Action<T>
and returns an Action
. In general, an Action<T>
is a delegate that accepts a single parameter of type T
and returns void
. In particular, Foo
is an Action<int>
because it accepts one parameter of type int
and returns void
. As for the return type of Curry
, it is declared as an Action
. An Action
is a delegate the has no parameters and returns void
.
The definition of Curry
is rather interesting. We are defining an action using a lambda expression which is a very special form of an anonymous delegate. Effectively
() => action(parameter)
says that the void
parameter is mapped to action
evaluated at parameter
.
Finally, in Main
we are declaring an instance of Action
named curried
that is the result of applying Curry
to Foo
with the parameter 5
. This plays the same role as bind(fun_ptr(foo), 5)
in your C++ example.
Lastly, we invoke the newly formed delegate curried
via the syntax curried()
. This is like someCallback()
in your example.
The fancy term for this is currying.
As a more interesting example, consider the following:
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));
}
}
Here we are declaring a method Curry
that accepts a delegate (Func<TArg, TArg, TResult>
that accepts two parameters of the same type TArg
and returns a value of some other type TResult
and a parameter of type TArg
and returns a delegate that accepts a single parameter of type TArg
and returns a value of type TResult
(Func<TArg, TResult>
).
Then, as a test we declare a method Add
that accepts two parameters of type int
and returns a parameter of type int
(a Func<int, int, int>
). Then in Main
we instantiate a new delegate named addFive
that acts like a method that adds five to its input parameter. Thus
Console.WriteLine(addFive(7));
prints 12
on the console.
这篇关于(如何)可以绑定/重新绑定一个方法来处理不同签名的代理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!