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

无法从List <DerivedClass>转换为List <BaseClass>

无法从List <DerivedClass>转换为List <BaseClass>

C#
慕桂英4014372 2019-10-11 10:08:02
我正在尝试将A的列表传递DerivedClass给采用的列表的函数BaseClass,但出现错误:cannot convert from 'System.Collections.Generic.List<ConsoleApplication1.DerivedClass>' to 'System.Collections.Generic.List<ConsoleApplication1.BaseClass>'现在,我可以将其强制List<DerivedClass>转换为List<BaseClass>,但是这样做不舒服,除非我理解为什么编译器不允许这样做。我发现的解释只是说它某种程度上违反了类型安全性,但我没有看到它。谁能帮我吗?编译器允许从List<DerivedClass>到转换的风险是什么List<BaseClass>?这是我的SSCCE:class Program{    public static void Main()    {        BaseClass bc = new DerivedClass(); // works fine        List<BaseClass> bcl = new List<DerivedClass>(); // this line has an error        doSomething(new List<DerivedClass>()); // this line has an error    }    public void doSomething(List<BaseClass> bc)    {        // do something with bc    }}class BaseClass{}class DerivedClass : BaseClass{}
查看完整描述

3 回答

?
慕村225694

TA贡献1880条经验 获得超4个赞

这是因为List<T>is in-variant而不是co-variant,所以您应该更改为IEnumerable<T>support co-variant,它应该起作用:


IEnumerable<BaseClass> bcl = new List<DerivedClass>();

public void doSomething(IEnumerable<BaseClass> bc)

{

    // do something with bc

}

有关泛型协变量的信息


查看完整回答
反对 回复 2019-10-11
?
慕哥9229398

TA贡献1877条经验 获得超6个赞

我发现的解释只是说它某种程度上违反了类型安全性,但我没有看到它。编译器允许从List<DerivedClass>到转换的风险是什么List<BaseClass>?


几乎每天都会问这个问题。


A List<Mammal>不能转换为a,List<Animal>因为您可以将蜥蜴放入一系列动物中。A List<Mammal>无法转换为a,List<Giraffe>因为列表中可能已经有老虎了。


因此List<T>必须在T中不变。


但是,List<Mammal>可以转换为IEnumerable<Animal>(从C#4.0开始),因为没有方法IEnumerable<Animal>可以添加蜥蜴。在T中IEnumerable<T>是协变的


查看完整回答
反对 回复 2019-10-11
?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

您描述的行为称为协方差 –如果A 为is B,List<A> 则为is List<B>。


但是,对于像这样的可变类型List<T>,从根本上讲是不安全的。


如果有这种可能,该方法将能够在new OtherDerivedClass()实际上只能容纳的列表中添加一个DerivedClass。


协方差对于不可变类型是安全的,尽管.Net仅在接口和委托中支持它。

如果您将List<T>参数更改为IEnumerable<T>,则可以使用


查看完整回答
反对 回复 2019-10-11
  • 3 回答
  • 0 关注
  • 404 浏览

添加回答

举报

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