C# 如何从 Lambda 表达式推断重载

问题描述 投票:0回答:1

最近我很惊讶 C# 中的一段特定语法以一种“神奇”的方式工作。此语法具有多个重载,仅通过

Action<T>
Func<T>
参数中的泛型类型进行区分。这可能是由于更熟悉 C++ 语法而产生的偏差,但令我惊讶的是,msbuild 能够仅基于 lambda 表达式正确选择重载,甚至不需要指定 lambda 参数的类型。

using System;

namespace Test1;

internal class Program
{
    public static void Main(string[] args)
    {
        // Picks overload #1 - somehow knows that x must be an int.
        Accept(x => x = 1);

        // Picks overload #2 - somehow knows that x must be a string.
        Accept(x => x.ToLower());
    }
    
    // Overload #1
    private static void Accept(Action<int> action) => action(0);

    // Overload #2
    private static void Accept(Action<string> action) => action("abc");
}

我很有趣的是,如何将

x => x = 1
正确推断为
Overload #1
,以及如何将
x => x.ToLower()
正确推断为
Overload #2
。我本以为我必须明确 lambda 表达式的类型。例如,
Accept((int x) => x = 1);
Accept((string x) => x.ToLower());

C# 标准或其他地方是否有任何内容能够解释这是如何发生的,以及这种推断可能在什么条件或规则下发生?

c# .net msbuild expression type-inference
1个回答
0
投票

类型是根据用法推断的。虽然 int 可以转换为字符串,但它不能隐式完成,因此第一个选项是通过兼容赋值推断的。 int 也没有 .ToLower() 扩展方法,因此第二个选项可以推断为字符串类型。另一方面,如果您的类型更加模糊,您会收到错误。

public static void Main(string[] args)
{
    // Produces Error CS0121
    Accept(x => x = 1);
}
    
// Overload #1
private static void Accept(Action<int> action) => action(0);

// Overload #2
private static void Accept(Action<long> action) => action(1L);
© www.soinside.com 2019 - 2024. All rights reserved.