- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个带有协变类型参数的接口(interface):
interface I<out T>
{
T Value { get; }
}
另外,我有一个非泛型基类和另一个从它派生的基类:
class Base
{
}
class Derived : Base
{
}
协方差表示 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?)
}
}
为什么这两个案例不一样对待?
最佳答案
Covariance says that an
I<Derived>
can be assigned to anI<Base>
正确。
Why are these two cases not treated the same?
您的陈述过于笼统了。你的逻辑似乎是这样的:
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
对您的泛型类型参数进行约束,然后它将按您预期的方式工作。
关于c# - 一般约束类中的协方差误差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50935140/
在我的设置中,我试图有一个界面 Table继承自 Map (因为它主要用作 map 的包装器)。两个类继承自 Table - 本地和全局。全局的将有一个可变的映射,而本地的将有一个只有本地条目的映射。
Rust Nomicon 有 an entire section on variance除了关于 Box 的这一小节,我或多或少地理解了这一点和 Vec在 T 上(共同)变体. Box and Vec
我是一名优秀的程序员,十分优秀!