9

ST不同时,这有效:

public static void Fun<S, T>(Func<S, T> func)
{

}

Fun((string s) => true); //compiles, T is inferred from return type.

但,

public static void Fun<T>(Func<T, T> func)
{

}

Fun(t => true); //can't infer type.

在第一个例子中,既然T是从 lambda 表达式的返回类型推断出来的,那么T在第二个例子中也不能推断出来吗?我想它正在这样做,但是为什么第一个T不知道,当第二个T知道时Func<T, T>T == T好吧?或者在 s 的情况下是否有推断类型的顺序Func

4

2 回答 2

13

这与 S 和 T 不同无关。它与您在第一种情况下提供形式参数类型而在第二种情况下不提供它有关。

在知道委托的形式参数类型之前,方法类型推断不会尝试从 lambda 推断委托的返回类型。

在第二种情况下,您没有给编译器任何东西来推断形式参数类型 T,因此甚至不会分析 lambda 的主体。

“形式参数类型”是什么意思?

形式参数是一个变量,它采用传递给方法、索引器、构造函数、lambda 或匿名方法的参数的值。(或者,在outref形式参数的情况下,成为调用者提供的变量的别名。)形式参数是变量,因此具有类型

委托具有类型为 的delegate R Func<A, R>(A a);形式参数。您使用要制作的方法类型参数构造它,因此委托的形式参数类型现在是。类型推断的任务是推断这些类型和.aAFunc<S, T>SST

在您的第一个示例中,您有一个带有stype 形式参数的lambda string。所以类型推断的原因是,既然这个 lambda 参数对应于func方法Fun的形参,而形参类型func是的,Func<S, T>那么形参类型s必然对应S。由于您为 提供了形式参数类型sS因此推断为string

一旦做出推断,就T可以通过分析 lambda 的主体来推断。

在您的第二种情况下,没有为t. 由于没有其他东西t可以推断出的类型,因此类型推断放弃并放弃在查看主体之前分析此 lambda。

碰巧的是,在您的情况下,可以独立于 lambda 的形式参数类型来分析主体。这是一种罕见的情况,类型推断算法并不是为了利用它而编写的。

如果这是您想要的类型推断,请考虑使用 F# 而不是 C#。它有一个更先进的类型推断算法,基于 Hindley-Milner 算法。

于 2013-02-12T17:08:35.373 回答
5

lambda 和其他函数的通用参数由它们的参数类型决定,而不是它们的返回类型。这与您不能这样做的原因完全相同:

T Foo<T>() { return default(T); }

string x = Foo(); // error

对于表达式t => true,我们显然不知道t可能是什么,因此编译器无法仅基于此做出任何决定。

于 2013-02-12T16:45:22.867 回答