考虑下面的例子。如果我首先定义一个委托(delegate)类型的变量,我就可以调用委托(delegate)的扩展方法。但我无法在作为参数传递 的委托(delegate)上调用该扩展方法。我不明白为什么它第一次起作用但第二次不起作用。我做错了什么?
public static class Extender
{
public static Func<String, String> Compose(this Func<String, String> outer, Func<String, String> inner)
{
return input => outer(inner(input));
}
}
public class Demo
{
public void WillingToTakeStringToStringDelegate(Func<String, String> map)
{
// blah
}
public void RunMe()
{
Func<String, String> outer = x => "(outer: " + x + ")";
// this works:
var composition = outer.Compose(x => "(inner: " + x + ")");
Trace.Write(composition("!")); // ---> (outer: (inner: !))
// this doesn't work:
this.WillingToTakeStringToStringDelegate(
(x => "(outer: " + x + ")").Compose(y => "(inner: " + y + ")")
);
}
}
更新
@philologon
只要您不介意必须将 lambda 赋值给变量,那么可以,您可以像老板一样使用此方法创建函数的部分应用程序(柯里化(Currying)):
public static class CurryingHelper
{
public static Func<X> Apply<A, X>(this Func<A, X> fun, A a)
{
return () => fun(a);
}
public static Func<B, X> Apply<A, B, X>(this Func<A, B, X> fun, A a)
{
return b => fun(a, b);
}
public static Func<B, C, X> Apply<A, B, C, X>(this Func<A, B, C, X> fun, A a)
{
return (b, c) => fun(a, b, c);
}
public static Func<B, C, D, X> Apply<A, B, C, D, X>(this Func<A, B, C, D, X> fun, A a)
{
return (b, c, d) => fun(a, b, c, d);
}
// etc...
}
public class Demo
{
public void RunMe()
{
Func<Int32, Int32, Int32, Int32> func = (a, b, c) => a - b + c;
var funcA1 = func.Apply(1);
Trace.Write(funcA1(2, 3)); // --> 2
Trace.Write(funcA1.Apply(2).Apply(3)()); // --> 2
}
}
最佳答案
构思没有问题,只是执行上有些技术问题。
重点是 x => "(outer: "+ x + ")"
不是没有上下文的委托(delegate):它是一个 lambda 表达式对应于一个委托(delegate)(一些类型)甚至是一个表达式树。因此必须显式或隐式声明类型,例如
// this works:
this.WillingToTakeStringToStringDelegate(
((Func<string, string>)(x => "(outer: " + x + ")")).Compose(...)
);
这与您不能将 lambda 函数分配给隐式类型变量的原因完全相同,例如
var f1 = (string s) => "Hello " + s; // does not work
Func<string, string> f2 = (string s) => "Hello " + s; // works fine
关于c# - 无法使扩展方法在委托(delegate)上工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19525095/