Kyle
Kyle

Reputation: 17677

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;

I would like to convert the list to its base class, and have tried: IList<Vehicle> baseList = cars as IList<Vehicle>;

But I always get 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?

Upvotes: 10

Views: 5663

Answers (8)

Dwedit
Dwedit

Reputation: 754

Note that IReadOnlyList<T> from .NET 4.5+ will allow you to cast IReadOnlyList<Car> into IReadOnlyList<Vehicle> with no problems. List<T> and Collection<T> implement this interface.

Upvotes: 0

PhistucK
PhistucK

Reputation: 2546

If you must use IList all of the way, then you are out of luck and the answers above can help you. 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.

// 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.

Upvotes: 0

Bolek Tekielski
Bolek Tekielski

Reputation: 1214

You can also take a look on Krzysztof's Cwalina article, Simulated Covariance for .NET Generics

Upvotes: 2

Marc Wittke
Marc Wittke

Reputation: 3155

You're facing the problem that there is limited co- and contravariance in C#. There is an interesting approach in C# 4.0, described here at the very ending. However, it creates some other limitations that are related to the truck-problem in the answer from Novelocrat.

Upvotes: 4

Abhijeet Patel
Abhijeet Patel

Reputation: 6878

var vehicles = cars.OfType<IVehicle>()

Upvotes: 1

recursive
recursive

Reputation: 86084

Here are a couple of approaches using 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));

Upvotes: 3

Phil Miller
Phil Miller

Reputation: 38118

That sort of polymorphism that lets you cast IList<Car> to IList<Vehicle> is unsafe, because it would let you insert a Truck in your IList<Car>.

Upvotes: 12

Lee
Lee

Reputation: 144136

Use 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.

Upvotes: 21

Related Questions