为了账号安全,请及时绑定邮箱和手机立即绑定

一般约束类中的协方差错误

一般约束类中的协方差错误

C#
绝地无双 2021-08-22 14:55:57
我有一个带有协变类型参数的接口:interface I<out T>{    T Value { get; }}此外,我有一个非通用基类和另一个派生自它:class Base{}class Derived : Base{}协方差说 anI<Derived>可以分配给 an 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?)    }}为什么这两种情况不一样对待?
查看完整描述

2 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

协方差说 anI<Derived>可以分配给一个I<Base>

正确。

为什么这两种情况不一样对待?

你从你的陈述中过度概括了。你的逻辑似乎是这样的:

  • 协方差说 anI<Derived>可以分配给一个I<Base>

  • DerivedBase是具有超类型-子类型关系的任意类型。

  • 因此协方差适用于任何具有超类型-子类型关系的类型。

  • 因此协方差适用于被限制为具有这种关系的泛型类型参数。

虽然看似合理,但这条逻辑链是错误的。正确的逻辑链是:

  • 协方差说 anI<Derived>可以分配给一个I<Base>

  • DerivedBase是具有超类-子类关系的任意引用类型。

  • 因此协方差适用于任何 具有超类-子类关系的引用类型。

  • 因此协方差适用于被限制为具有这种关系的引用类型的泛型类型参数。

在您的示例中,一个人完全有权制作Foo<int, object>. 由于I<int>无法转换为I<object>,编译器拒绝转换I<TDerived>I<TBase>。请记住,编译器必须证明泛型方法适用于所有可能的构造,而不仅仅是您所做的构造。泛型不是模板。

错误信息可能更清楚,我同意。对于糟糕的体验,我深表歉意。改进那个错误在我的清单上,我从来没有做过。

你应该class对你的泛型类型参数施加约束,然后它就会像你期望的那样工作。


查看完整回答
反对 回复 2021-08-22
?
ibeautiful

TA贡献1993条经验 获得超5个赞

通用参数TDerivedTBase没有对您创建的类DerivedBase 的引用。它只是与您在 where 子句中描述的关系相同的任何类的别名


查看完整回答
反对 回复 2021-08-22
  • 2 回答
  • 0 关注
  • 148 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信