Func<;S、 T>;仅当S和T不同时,才从lambda表达式的输出推断

本文关键字:表达式 lambda 才从 输出 gt lt 仅当 Func | 更新日期: 2023-09-27 17:59:00

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是未知的,而Func<T, T>的第二个T是已知的,毕竟T == T是对的?或者,在Func s的情况下,是否有推断类型的顺序?

Func<;S、 T>;仅当S和T不同时,才从lambda表达式的输出推断

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

方法类型推断不会尝试从lambda推断委托的返回类型,直到该委托的形式参数类型为已知为止。

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

你所说的"形式参数类型"是什么意思?

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

委托delegate R Func<A, R>(A a);具有类型为A的形式参数a。您使用方法类型参数构造它,使其成为Func<S, T>,因此委托的形式参数类型现在是S。类型推断的任务是推断出CCD_ 17和CCD_。

在第一个示例中,您有一个lambda,其形式参数s的类型为string。因此类型推断的原因是,由于这个lambda参数对应于方法Fun的形式参数func,并且func的形式参数类型是Func<S, T>,那么s的形式参数必须对应于S。由于您为s提供了一个形式化的参数类型,因此S被推断为string

一旦进行了该推断,则可以通过分析lambda的主体来推断CCD_ 30。

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

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

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

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

T Foo<T>() { return default(T); }
string x = Foo(); // error

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