Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Covariance with C# Generics

Tags:

Given an interface IQuestion and an implementation of that interface AMQuestion, suppose the following example:

List<AMQuestion> typed = new List<AMQuestion>(); IList<IQuestion> nonTyped = typed; 

This example yields, as expected, a compile error saying the two are not of the same type. But it states an explicit conversion exists. So I change it to look like this:

List<AMQuestion> typed = new List<AMQuestion>(); IList<IQuestion> nonTyped = typed as IList<IQuestion>; 

Which then compiles but, at run time, nonTyped is always null. If someone could explain two things:

  • Why this doesn't work.
  • How I can achieve the desired effect.

It would be greatly appreciated. Thank you!

like image 274
Will Custode Avatar asked Jun 18 '14 13:06

Will Custode


1 Answers

The fact that AMQuestion implements the IQuestion interface does not translate into List<AMQuestion> deriving from List<IQuestion>.

Because this cast is illegal, your as operator returns null.

You must cast each item individually as such:

IList<IQuestion> nonTyped = typed.Cast<IQuestion>().ToList(); 

Regarding your comment, consider the following code, with the usual cliché animal examples:

//Lizard and Donkey inherit from Animal List<Lizard> lizards = new List<Lizard> { new Lizard() }; List<Donkey> donkeys = new List<Donkey> { new Donkey() };  List<Animal> animals = lizards as List<Animal>; //let's pretend this doesn't return null animals.Add(new Donkey()); //Reality unravels! 

if we were allowed to cast List<Lizard> to a List<Animal>, then we could theoretically add a new Donkey to that list, which would break inheritance.

like image 51
Rotem Avatar answered Jan 04 '23 01:01

Rotem