【问题标题】:C# Type Inference fails with methods that contain default parametersC# 类型推断因包含默认参数的方法而失败
【发布时间】:2015-02-13 05:31:50
【问题描述】:

假设我有以下方法:

static int MethodWithDefaultParameters(int a, int b=0, int c=1)
{
    return a + b + c;
}

然后我在 LINQ 查询中使用此方法,如下所示:

Enumerable.Range(1,10).Select(MethodWithDefaultParameters);

这失败了:

错误 1 ​​无法从用法中推断方法“System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)”的类型参数。尝试明确指定类型参数。

当然,我可以通过插入一个转发函数调用的 lambda 来解决这个问题,如下所示:

Enumerable.Range(1,10).Select(i => MethodWithDefaultParameters(i));

但我的问题是为什么类型推断会失败?据我所知,它不应该是模棱两可的,因为只有一个函数的变体满足输入变量。

【问题讨论】:

    标签: c# type-inference


    【解决方案1】:

    Select() 有两个重载。一个采用Func<TSource, TResult> 作为第二个参数(即委托),另一个采用Func<TSource, int, TResult>。 IE。带有一个或两个参数的方法签名。

    你的方法都不满足。即使使用默认值,它仍然具有三个参数。默认参数是 compile-time 构造,必须在调用站点提供。它们不会在运行时通过调用委托实例来填充。

    因此,事实上,您的解决方法是解决问题的两种合理方法之一。另一种是以不同的方式实现默认参数(即“老派”:)):

    static int MethodWithDefaultParameters(int a)
    {
        return MethodWithDefaultParameters(a, 0, 1);
    }
    
    static int MethodWithDefaultParameters(int a, int b, int c)
    {
        return a + b + c;
    }
    

    然后您可以在对Select() 的调用中直接使用MethodWithDefaultParameters,因为编译器会找到与Select() 重载之一兼容的单参数重载。

    【讨论】:

    • 啊哈,就类型推理引擎而言,MethodWithDefaultParameters 的签名将始终带有三个参数 - 即它永远不会看到只有一个参数的版本。谢谢你的解释!
    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 2021-12-22
    • 2018-12-13
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    • 2022-01-06
    • 1970-01-01
    相关资源
    最近更新 更多