naw*_*fal 9 c# generics type-inference func
当S
和T
不同时,这有效:
public static void Fun<S, T>(Func<S, T> func)
{
}
Fun((string s) => true); //compiles, T is inferred from return type.
Run Code Online (Sandbox Code Playgroud)
但,
public static void Fun<T>(Func<T, T> func)
{
}
Fun(t => true); //can't infer type.
Run Code Online (Sandbox Code Playgroud)
在第一个例子中,既然T
是从lambda表达式的返回类型推断出来的,那么T
在第二个例子中也不能推断出来?我想它这样做,但为什么第一次T
不知道,如果将第二T
的Func<T, T>
是已知的,毕竟T == T
对不对?或者在Func
s的情况下是否有推断类型的订单?
Eri*_*ert 13
它与S和T不同,没有任何关系.它与您在第一种情况下提供形式参数类型而在第二种情况下不提供它有关.
方法类型推断不会尝试从lambda推断委托的返回类型,直到知道委托的形式参数类型为止.
在第二种情况下,你没有给编译器任何推断形式参数类型T的东西,因此甚至不会分析lambda的主体.
"形式参数类型"是什么意思?
形式参数是一个变量,它接受传递给方法,索引器,构造函数,lambda或匿名方法的参数的值.(或者,在out
和ref
参数形式的情况下,成为调用者提供的变量的别名.)形式参数是变量,因此具有类型.
委托delegate R Func<A, R>(A a);
具有a
类型的形式参数A
.您可以使用方法类型参数构造它Func<S, T>
,因此委托的形式参数类型现在是S
.类型推断的任务是推断那些类型S
和T
.
在你的第一个例子中,你有一个带有形式参数s
类型的lambda string
.所以类型推断的原因是因为这拉姆达参数对应于形参func
的方法Fun
,并正式参数类型func
是Func<S, T>
那么正式的参数类型s
必须对应S
.由于您给出了正式的参数类型s
,S
因此推断为string
.
一旦做出推断,则T
可以通过分析lambda的主体来推断.
在第二种情况下,没有给出正式的参数类型t
.由于没有其他任何类型t
可以推导出来,因此类型推断会放弃并放弃在查看正文之前分析这个lambda.
恰好在你的情况下,可以独立于lambda的形式参数类型来分析主体.这是一种罕见的情况,并且没有编写类型推断算法来利用它.
如果这是您想要的类型推断,请考虑使用F#而不是C#.它具有更先进的类型推断算法,基于Hindley-Milner算法.
lambdas和其他函数的通用参数由它们的参数类型决定,而不是它们的返回类型.这与你不能这样做的原因完全相同:
T Foo<T>() { return default(T); }
string x = Foo(); // error
Run Code Online (Sandbox Code Playgroud)
对于表达式t => true
,我们显然不知道t
可能是什么,因此编译器不能仅基于此做出任何更多的决策.