Why won't the following code work?
class parent {}
class kid:parent {}
List<parent> parents=new List<kid>;
It seems obvious to me. What's going on here?
Why won't the following code work?
class parent {}
class kid:parent {}
List<parent> parents=new List<kid>;
It seems obvious to me. What's going on here?
C# does not currently support covariance.
It's coming in .NET 4.0, however, on interfaces and delegates.
Eric Lippert had a very nice series on this subject on his blog awhile back. Visual Studio Magazine covers it too in a recent article.
Besides the lack of generic variance support in C# prior to version 4.0, List is mutable and so cannot safely be covariant. Consider this:
void AddOne<T>(List<T> arg) where T : new()
{
arg.Add(new T());
}
void Whoops()
{
List<parent> contradiction = new List<kid>();
AddOne(contradiction); // what should this do?
}
This would attempt to add a Parent to a List referenced via a List reference, which is not safe. Arrays are permitted to be covariant by the runtime, but are type-checked at mutation time and an exception is thrown if the new element is not assignable to the array's runtime element type.
The feature you are looking for is called covariance. It is not supported in C# until version 4.0 and then only on interfaces and delegates.
Some links on the subject
If you know that the List<Parent>
contains List<child>
you can use an extension method to 'convert', (really just take the Parents that ARE of type child and return them in a list. eg something like:
public static List<T> Convert<T, T2>(this List<T2> input) {
return input.OfType<T>().ToList();
}
Im not sure if this helps you, but my 2 cents worth! I use it quite alot.
As has been pointed out, this isn't currently supported in C#. In Java, arrays are covariant, and it can cause some problems. Consider your example, the actual list should be a list of "kid", meaning all the objects in it should be "kid"s (or "grandchildren"). But if the reference you're using to access the list is a list of "parent" then you could insert a "parent" into the list which obviously shouldn't happen.