我觉得像下面这样的东西,在c中可能有可能在c#与代表.这里是一些psudo代码,我将在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#代理的绑定/重新绑定的引用.我错过了什么吗?在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的委托.特别地,Foo是Action< int>因为它接受一个int类型的参数并返回void.对于咖喱的返回类型,它被声明为一个Action.一个Action是一个没有参数的代理,返回void.
咖喱的定义颇有意思.我们使用lambda表达式定义一个动作,这是一个非常特殊形式的匿名委托.有效
() => action(parameter)
说void参数映射到参数评估的动作.
最后,在Main中,我们将声明一个Action的实例名为curried,这是使用参数5将Curry应用于Foo的结果.这与C(例如)中的bind(fun_ptr(foo),5))起着同样的作用.
最后,我们通过语法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,TResult>接受相同类型TArg的两个参数,并返回一些其他类型的TResult的值和一个类型为TArg的参数,并返回接受的代理类型为TArg的单个参数,并返回类型为TResult(Func< TArg,TResult>)的值.
然后,作为测试,我们声明一个方法Add,它接受类型为int的两个参数,并返回一个类型为int(一个Func< int,int,int>)的参数.然后在Main中,我们实例化一个名为addFive的新委托,它的作用就像一个向输入参数添加五个方法.从而
Console.WriteLine(addFive(7));
在控制台上打印12张.