简体   繁体   English

列表<Type>到 IList<BaseType>

[英]IList<Type> to IList<BaseType>

I have a few classes:我有几节课:

class Vehicle
{
}

class Car : Vehicle
{
}

I have a list of the derived class: IList<Car> cars;我有一个派生类的列表: IList<Car> cars;

I would like to convert the list to its base class, and have tried: IList<Vehicle> baseList = cars as IList<Vehicle>;我想将列表转换为其基类,并尝试过: IList<Vehicle> baseList = cars as IList<Vehicle>;

But I always get null .但我总是得到null Also

cars is IList<Vehicle> evaluates to be false.

Granted, I can add the items to a list if I do the following:当然,如果我执行以下操作,我可以将项目添加到列表中:

List<Vehicle> test = new List<Vehicle> ();

foreach ( Car car in cars )
{
   test.Add(car);
}

And I get my list, but I know there has to be a better way.我得到了我的清单,但我知道必须有更好的方法。 Any thoughts?有什么想法吗?

Use IEnumerable <T> .Cast :使用IEnumerable <T> .Cast

IList<Vehicle> vehicles = cars.Cast<Vehicle>().ToList();

Alternatively, you may be able to avoid the conversion to List depending on how you wish to process the source car list.或者,您可以避免转换为 List,具体取决于您希望如何处理源汽车列表。

那种让您将IList<Car>IList<Vehicle>的多态性是不安全的,因为它会让您在IList<Car>插入Truck

You're facing the problem that there is limited co- and contravariance in C#.您面临的问题是 C# 中的协变和逆变有限。 There is an interesting approach in C# 4.0, described here at the very ending . C# 4.0 中有一个有趣的方法, 在最后的. However, it creates some other limitations that are related to the truck-problem in the answer from Novelocrat.但是,它在 Novelocrat 的答案中产生了一些与卡车问题相关的其他限制。

Here are a couple of approaches using Linq:以下是使用 Linq 的几种方法:

IList<Derived> list = new List<Derived>();
list.Add(new Derived());

IList<Base> otherlist = new List<Base>(from item in list select item as Base);
IList<Base> otherlist2 = new List<Base>(list.Select(item => item as Base));

您还可以查看 Krzysztof 的 Cwalina 文章Simulated Covariance for .NET Generics

var vehicles = cars.OfType<IVehicle>()

If you must use IList all of the way, then you are out of luck and the answers above can help you.如果您必须一直使用IList ,那么您就不走运了,上面的答案可以帮助您。 However, if you can use an IList that is casted as IEnumerable and then simply re-casted at the destination as IList , that would work, since IEnumerable can accept such practice.但是,如果您可以使用转换为IEnumerableIList ,然后简单地在目标位置重新转换为IList ,那将起作用,因为IEnumerable可以接受这种做法。

// At the source or at the model.
IEnumerable<BaseType> list = new List<Type>();
// At the destination.
IList<BaseType> castedList = (IList<BaseType>)list;

Although, since the compiler cannot enforce these things, you must manually make sure that the types and base types indeed match, of course.虽然,由于编译器无法强制执行这些操作,当然您必须手动确保类型和基类型确实匹配。

Note that IReadOnlyList<T> from .NET 4.5+ will allow you to cast IReadOnlyList<Car> into IReadOnlyList<Vehicle> with no problems.请注意,.NET 4.5+ 中的IReadOnlyList<T>将允许您将IReadOnlyList<Car>转换为IReadOnlyList<Vehicle>没有问题。 List<T> and Collection<T> implement this interface. List<T>Collection<T>实现了这个接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM