我有一个带有协变类型参数的接口(interface):
interface I<out T>
{
T Value { get; }
}
另外,我有一个非泛型基类,并且派生自它:
class Base
{
}
class Derived : Base
{
}
Covariance表示可以将
I<Derived>
分配给I<Base>
,并且I<Base> ib = default(I<Derived>);
确实可以编译。但是,此行为显然会随着具有继承约束的通用参数而发生变化:
class Foo<TDerived, TBase>
where TDerived : TBase
{
void Bar()
{
I<Base> ib = default(I<Derived>); // Compiles fine
I<TBase> itb = default(I<TDerived>); // Compiler error: Cannot implicitly convert type 'I<TDerived>' to 'I<TBase>'. An explicit conversion exists (are you missing a cast?)
}
}
为什么这两种情况不一样?
最佳答案
正确的。
您的陈述过于笼统。您的逻辑似乎是这样的:
I<Derived>
分配给I<Base>
Derived
和Base
是具有父类(super class)型与子类型关系的任意类型。 尽管合理,但这种逻辑链是错误的。正确的逻辑链是:
I<Derived>
分配给I<Base>
Derived
和Base
是具有父类(super class)-子类关系的任意引用类型。 在您的示例中,制作
Foo<int, object>
完全在权限之内。由于I<int>
无法转换为I<object>
,因此编译器拒绝从I<TDerived>
转换为I<TBase>
的转换。请记住,编译器必须证明通用方法才能对所有可能的构造起作用,而不仅仅是您所做的构造。泛型不是模板。我同意,错误消息可能更清晰。我为糟糕的经历表示歉意。改善该错误已列在我的 list 上,但我从未做到。
您应该在通用类型参数上添加
class
约束,然后它将按预期工作。