c# - 无法使扩展方法在委托(delegate)上工作

标签 c# delegates extension-methods

考虑下面的例子。如果我首先定义一个委托(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/

相关文章:

c# - 如何获取DataTable中某列的SqlType?

c# - 如何捕获 CheckInvalidPathChars() 异常

c# - 将算法从 C# 转换为 VB.NET 失败

c# - 我执行 : c# extension methods 有什么问题

c# - 方法参数中的 'this' 关键字是什么意思?

c# - 跨静态类共享数据库连接的正确设计?

c# - 如何使所有平台的 View 相同

C# - 重写对 Action<> 的委托(delegate)调用

ios - 如何通过iOS Swift中的回调函数发送JSON响应数据?

ios - 如果属性更改则调用委托(delegate)方法