为什么在 C# 中我可以将委托变量作为泛型参数传递,而不是方法

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

我有这两种方法:

string Foo<T>(Func<T, string> f) => throw new NotImplementedException();
string Bar(int x) => x.ToString();

为什么我可以在 C# 中将一个方法分配给一个变量,然后将该变量传递给一个方法:

var f = Bar;
Foo(f); // compiles just fine

但不直接传方法?

Foo(Bar);

这会产生编译错误

无法从用法中推断出方法“Program.Foo(Func)”的类型参数。尝试显式指定类型参数。

为什么变量赋值可以推断类型,而实参赋值却不能推断类型?

编辑:

Eric Lippert 在 2011 年回答过

具体来说,细微的区别在于方法组是 被认为可以仅根据以下条件转换为委托类型 参数是否匹配,而不是还基于是否 返回类型匹配。 Lambdas 检查参数和返回值 类型。

根据 C# 12 规范和方法组转换,情况似乎仍然如此:

如果使用类型推断,委托的参数类型为 在推理过程中用作参数类型。返回类型为 委托不用于推理

但这与 C# 编程指南和委托冲突:

从 C# 10 开始,具有单个重载的方法组具有 自然型。这意味着编译器可以推断返回类型并 委托类型的参数类型:

var read = Console.Read;

这意味着编译器确实能够将一组方法转换为委托。那么直接传递方法组时为什么不做同样的事情呢?

c# generics type-inference
1个回答
0
投票

var f = Bar
将隐式创建一个指向 Bar 的 Delegate。您可以立即将
Bar
声明为委托,它将起作用。见下文。

using System;
                    
public class Program
{
    public static void Main()
    {
        string Foo<T>(Func<T, string> f) => throw new NotImplementedException();
        Func<int, string> Bar = x => x.ToString();
        
        var f = Bar;
        Foo(f); // compiles just fine
        
        Foo(Bar); // also compiles 
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.