【问题标题】:Why won't my generic higher order function accept a method group as argument?为什么我的通用高阶函数不接受方法组作为参数?
【发布时间】:2017-08-09 09:43:12
【问题描述】:

我有以下本地方法。

void Test(int i, int j, int k) {
    Console.WriteLine($"{i} {j} {k}");
}

我有一个如下定义的高阶函数

public static class Curry {
    public static Func<T0, T1, Action<T2>> 
        act2f3<T0, T1, T2>(Action<T0, T1, T2> fn) =>
           (T0 t0, T1 t1) => (T2 t2) => fn(t0, t1, t2);

}

它将原始函数拆分为两个函数调用。第一个函数接受前两个参数,第二个函数接受最后一个参数。当第二个函数被调用时,原始函数被调用,所有参数都被调用。

一个简单的用法是

var cfn = Curry.act2f3( Test );
var cfn2 = cfn(0,1);
cfn2(3); 

cfn2调用后的输出应该是

"0 1 3"    

但是 C# 编译器不允许这样做。

方法“Curry.act2f3(Action)”的类型参数无法从用法中推断出来。尝试指定类型 显式参数。

但是以下确实有效

 Curry.act2f3( (int i, int j, int k) => Test( i, j, k ) );

但这并没有真正的帮助,因为它首先违背了编写这个库的目的。目的是一个DRY 处理函数参数的过程。

我是否缺少一个微妙的技巧来使其正常工作?

【问题讨论】:

  • 通用类型推断没有实现深度启发式,它会经常停止一层或在它能够推断出所涉及的类型然后吐出那个错误之前。
  • 我经常将方法组传递给 LINQ 函数,没有问题。阻止方法组与 lambda 互换的具体问题是什么?
  • 这里的部分问题(我认为)是有两种类型的推理在起作用,它们委托围绕Test 构造,以及方法中的泛型类型。如果你试试这个:Curry.act2f3(new Action&lt;int, int, int&gt;(Test)); 然后它编译。
  • 我猜本地功能还很新,还有改进的余地。我在 CSharpLang 上打开了一个更改请求。也许会有所作为。 github.com/dotnet/csharplang/issues/798

标签: c# .net generics higher-order-functions currying


【解决方案1】:

不幸的是c#编译器无法推断传递函数Test的类型参数。

Curry.act2f3( (int i, int j, int k) =&gt; Test( i, j, k ) ); 语句有效,因为您在声明 (int i, int j, int k) 中指定了 int 类型。

如果您像这样指定泛型类型,var cfn = Curry.act2f3( Test ); 将起作用:

var cfn = Curry.act2f3&lt;int, int, int&gt;( Test );.

【讨论】:

    猜你喜欢
    • 2011-12-28
    • 2020-06-25
    • 2015-08-21
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多