好的,我的标题一定非常错误。更多代码,更少的单词:
public class Manager<T> where T : Control, new()
{
void Manage()
{
Do(t => IsVisible(t));
}
bool IsVisible(T t)
{
return t.Visible;
}
S Do<S>(Func<T, S> operation)
{
return operation(new T());
}
}
编译器对Do
感到高兴。它可以轻松推断出T
类型。现在让我说我有这个:
public static class Util
{
static void Manage()
{
Do(t => IsVisible(t)); //wiggly line here
}
static bool IsVisible<T>(T t) where T : Control
{
return t.Visible;
}
static S Do<S, T>(Func<T, S> operation) where T : Control, new()
{
return operation(new T());
}
}
编译器希望现在显式键入类型。这就是我的想法:
在第一课T
很容易被IsVisible
方法推断出T
重载,T
类已知Manager
, 没什么大不了。但在第二种情况下,T
被指定为方法的通用约束,并且可能更难以推断。确定。
但这也不起作用:
public static class Util
{
static void Manage()
{
Do(t => IsVisible(t)); //still wiggly line
}
static bool IsVisible(Control t)
{
return t.Visible;
}
static S Do<S, T>(Func<T, S> operation) where T : Control, new()
{
return operation(new T());
}
}
为什么编译器在最后一种情况下不推断T
?
更重要的是,最后一个案例与第一个案例有何不同?在第一种情况下,编译器必须从IsVisible
方法推断它,然后一直回去检查包含T
的类中IsVisible
是什么,在最后一种情况下它很容易以IsVisible
方式提供。所以我假设第三种情况比第一种情况容易。
答案 0 :(得分:4)
(第一个案例)
编译器对Do感到高兴。它可以很容易地推断出T型。
根本不会推断T
。 T
是类的类型参数:
public class Manager<T> where T : Control, new()
(第二个案例)
编译器希望现在显式键入类型。
我认为你的意思是在管理代码中:
Do(t => IsVisible(t))
那是对的。 你认为T
的类型应该在哪里?您如何期望编制者推断它?
(第三种情况,方法为IsVisible(Control t)
)
为什么编译器在最后一种情况下不推断T?
仅从参数中无法做到这一点。听起来你期望它可以解决lambda表达式的主体可以工作的每种类型......并且类型推断根本不起作用。您可以轻松地为编译器提供足够的信息:
Do((Control t) => IsVisible(t));
更重要的是,最后一个案例与第一个案例有何不同?
在第一种情况下,T
不是Do
方法的类型参数。编译器 only 需要推断S
,它可以从lambda表达式的返回类型中做到。它不需要对T
执行任何推断,因为它已经“已知”。 (它仍然是通用的,但它不是需要为该方法调用推断的东西。)构造T
的实例时需要提供Manager
的类型首先,它正在有效地推动这一决定。
有关类型推断的所有详细信息,请参阅C#4规范的7.5.2节(或C#3或C#5规范中的等效部分)。我先建议喝一杯浓咖啡,但是:)