猿问

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

我正在尝试将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

{

}


慕桂英4014372
浏览 408回答 3
3回答

慕村225694

这是因为List<T>is in-variant而不是co-variant,所以您应该更改为IEnumerable<T>support co-variant,它应该起作用:IEnumerable<BaseClass> bcl = new List<DerivedClass>();public void doSomething(IEnumerable<BaseClass> bc){&nbsp; &nbsp; // do something with bc}有关泛型协变量的信息

慕哥9229398

我发现的解释只是说它某种程度上违反了类型安全性,但我没有看到它。编译器允许从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>是协变的

Smart猫小萌

您描述的行为称为协方差 –如果A 为is B,List<A> 则为is List<B>。但是,对于像这样的可变类型List<T>,从根本上讲是不安全的。如果有这种可能,该方法将能够在new OtherDerivedClass()实际上只能容纳的列表中添加一个DerivedClass。协方差对于不可变类型是安全的,尽管.Net仅在接口和委托中支持它。如果您将List<T>参数更改为IEnumerable<T>,则可以使用
随时随地看视频慕课网APP
我要回答