为什么无法推断嵌套泛型类型?

16

假设有以下类...

public abstract class FooBase<TBar> where TBar : BarBase{}
public abstract class BarBase{}
public class Bar1 : BarBase{}
public class Foo1 : FooBase<Bar1> {}

...并且以下方法...

public TBar DoSomething<TFoo, TBar>(TFoo theFoo)
    where TFoo : FooBase<TBar>
    where TBar : BarBase
{
    return default(TBar);
}
为什么下面这行代码不能暗示返回类型?
Bar1 myBar = DoSomething(new Foo1());

相反,我必须像这样指定通用类型...

Bar1 myBar = DoSomething<Foo1, Bar1>(new Foo1());
1个回答

23

方法类型推断忽略方法类型参数上的泛型约束 (*). 方法类型推断仅考虑将参数形式参数类型进行比较所能得出的推论。由于您的形式参数类型中唯一出现的泛型类型参数是 TFoo,因此无法推导出 TBar。

许多人认为这种设计决策是错误的。尽管我理解他们的观点,但我认为这个决策确实带来了一些好处。关于这个问题的详细辩论,请参见此博客文章上数不清的评论,那里有许多人告诉我我是错的:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx


(*) 注意,我说忽略的是对方法类型参数的约束,而不是忽略所有约束。如果构造出的形式参数类型是泛型类型,并且该构造违反了它们的类型参数约束,则此事实会导致类型推断失败,该方法不是重载分辨过程的候选方法。但在任何情况下,我们都不会从除“嗯,显然这不起作用”之外的约束中做出推论。


我认为有些人会想知道为什么我们不会尝试使用约束来推断类型。另一种思考方法是,如果你首先要确定TFoo和TBar正在使用哪些具体类型,那么现在引用这些类型的任何代码都将使用具体类型。对于FooBase<TBar>,我们在这里说,在你知道TBar是什么类型之后,FooBase<TBar>将变成FeeBase<ActualType>。由于我们在推断完成之前不知道类型,因此无法将此约束用作类型推断的一部分。这将是循环逻辑。 - AaronLS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接