In C#, How to Cast a List<Child> to List<Parent>

In C#, is it possible to cast a ListChild to ListParent?

Casting directly is not allowed because there's no way to make it typesafe. If you have a list of giraffes, and you cast it to a list of animals, you could then put a tiger into a list of giraffes! The compiler wouldn't stop you, because of course a tiger may go into a list of animals. The only place the compiler can stop you is at the unsafe conversion.

In C# 4 we'll be supporting covariance and contravariance of SAFE interfaces and delegate types that are parameterized with reference types. See here for details:

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariance/

Casting a list of children to a list of parent types

Well to start with, you don't need to create an empty List<Review> which you then ignore :)

Here's the simplest solution:

public List<Review> GetReviews(string filePath)
{
XElement xmlDoc = XElement.Load(filePath);

var dtos = ...; // As before

return dtos.Cast<Review>().ToList();
}

If you're using .NET 4 and C# 4, there's another alternative due to generic covariance which works for IEnumerable<T> but not List<T>:

public List<Review> GetReviews(string filePath)
{
XElement xmlDoc = XElement.Load(filePath);

IEnumerable<Review> dtos = ...; // As before

return dtos.ToList();
}

Note the explicit specification of the type of dtos. The query expression will be of type IEnumerable<ShelfAwarenessReview> but that's implicitly convertible (in C# 4) to IEnumerable<Review>.

Convert List of Base Class to a List of Derived Class - possible?

Cast<T> method applies cast operation to all elements of the input sequence. It works only if you can do the following to each element of the sequence without causing an exception:

ParentClass p = ...
ChildClass c = (ChildClass)p;

This will not work unless p is assigned an instance of ChildClass or one of its subclasses. It appears that in your case the data returned from the server API contains objects of ParentClass or one of its subclasses other than ChildClass.

You can fix this problem by constructing ChildClass instances, assuming that you have enough information from the server:

List<ChildClass> childList = parentList
.Select(parent => new ChildClass(parent.Name, ... /* the remaining fields */))
.ToList();

Convert ListDerivedClass to ListBaseClass

The way to make this work is to iterate over the list and cast the elements. This can be done using ConvertAll:

List<A> listOfA = new List<C>().ConvertAll(x => (A)x);

You could also use Linq:

List<A> listOfA = new List<C>().Cast<A>().ToList();

List assignment from child to parent

Update: because the two types, List<Parent> and List<Child> is not co-variant.

Even though the generic parameter you pass in, Child, inherits Parent, the relationship is not carried into the closed List types. Thus, the resulting two List types are not interchangeable.

.Net 4.0 introduces co-variance/contra-variance. Your code will still not work with .Net 4.0 though, since neither the List class or the IList interface will be changed to be co-variant.

Casting populated ListBaseClass to ListChildClass

You can do this if you are really sure all items are castable:

ChildClassList = BaseClassList.Cast<ChildClass>().ToList();

Your current code adds null if a BaseClass item cannot be cast to ChildClass. If that was really your intention, this would be equivalent:

ChildClassList = BaseClassList.Select(x => x as ChildClass).ToList();

But i'd rather suggest this, which includes type checking and will skip items that don't match:

ChildClassList = BaseClassList.OfType<ChildClass>().ToList();


Related Topics



Leave a reply



Submit