将IList<Type>转换为IList<BaseType>

10

我有几个类:

class Vehicle
{
}

class Car : Vehicle
{
}

我有一个派生类的列表:     IList<Car> cars;

我想将列表转换为其基类,已经尝试过:     IList<Vehicle> baseList = cars as IList<Vehicle>;

但我总是得到null。另外

cars is IList<Vehicle> evaluates to be false.

如果按照以下步骤操作,我可以将项目添加到列表中:

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

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

我已经得到了我的列表,但我知道肯定有更好的方法。你有什么想法吗?


1
至少涉及到以下两个问题:https://dev59.com/ukfSa4cB1Zd3GeqPBfbe 和 http://stackoverflow.com/questions/1296892/c-interface-implementation-and-generic-collections-question。 - Steve Gilham
Robert Harvey:当然还有另一种方法;他可以创建一个 IList<BaseType> 的实现,基本上是对现有 IList<Type> 的包装。这样,他就不必强制转换所有元素,只需转换所需的元素即可。 - Tamas Czinege
8个回答

21

使用 IEnumerable<T>.Cast方法:

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

另外,根据您希望如何处理源汽车列表,您可能可以避免将其转换为List。


@Robert Harvey:.Net Framework 3.5 已经发布将近两年了。我认为可以安全地假设除非有很好的理由,否则每个人都已经拥有它了。 - Tamas Czinege
5
请注意,这将导致生成一个新的列表,而不是对同一列表的引用。 - configurator

12

那种允许你将 IList<Car> 强制转换为 IList<Vehicle> 的多态性是不安全的,因为它会让你向 IList<Car> 中插入一个 Truck


他不是试图转换它,而是创建一个新的列表实例。 - recursive
5
不,他试图将派生类型的列表引用分配给基础类型的列表引用,并想知道为什么会得到null。如果他试图创建一个新实例,这将完全正常。 - Phil Miller

4
你面临的问题是C#中协变性和逆变性有限。在C# 4.0中有一种有趣的方法,可以在这里的结尾处进行描述。然而,它会创建一些与Novelocrat回答中的卡车问题相关的其他限制。

3

以下是使用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));

2

1
var vehicles = cars.OfType<IVehicle>()

0
请注意,.NET 4.5+ 中的 IReadOnlyList<T> 可以让您将 IReadOnlyList<Car> 转换为 IReadOnlyList<Vehicle>,而不会出现任何问题。 List<T>Collection<T> 实现了此接口。

0
如果你必须一路使用 IList,那么你就很倒霉了,上面的答案可以帮助你。然而,如果你可以使用一个被转换为 IEnumerable 的 IList,并且在目标地点简单地重新转换为 IList,那么这将起作用,因为 IEnumerable 可以接受这种做法。
// At the source or at the model.
IEnumerable<BaseType> list = new List<Type>();
// At the destination.
IList<BaseType> castedList = (IList<BaseType>)list;

尽管编译器无法强制执行这些事情,当然您必须手动确保类型和基本类型确实匹配。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接