Ale*_*x Q 4 c# generics covariance
我有一个协变类型参数的接口:
interface I<out T>
{
T Value { get; }
}
Run Code Online (Sandbox Code Playgroud)
另外,我有一个非泛型基类,另一个派生自它:
class Base
{
}
class Derived : Base
{
}
Run Code Online (Sandbox Code Playgroud)
协方差说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?)
}
}
Run Code Online (Sandbox Code Playgroud)
为什么这两个案件不一样?
Eri*_*ert 11
协方差表示
I<Derived>可以分配给一个I<Base>
正确.
为什么这两个案件不一样?
你的陈述过于笼统.你的逻辑似乎是这样的:
I<Derived>可以分配给一个I<Base>Derived并且Base是具有超类型 - 子类型关系的任意类型.虽然看似合理,但这种逻辑链是错误的.正确的逻辑链是:
I<Derived>可以分配给一个I<Base>Derived并且Base是具有超类 - 子类关系的任意引用类型.在你的例子中,一个完全有权制作一个Foo<int, object>.由于I<int>无法转换为I<object>,编译器拒绝转换I<TDerived>为I<TBase>.请记住,编译器必须证明泛型方法适用于所有可能的构造,而不仅仅是您构造的构造.泛型不是模板.
我同意,错误信息可能更清楚.我为糟糕的经历道歉.改进这个错误在我的名单上,我从来没有这样做过.
您应该class对通用类型参数设置约束,然后它将按预期工作.