Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question about C# covariance

In the code below:

interface I1 { }
class CI1: I1 { }

List<CI1> listOfCI1 = new List<CI1>();

IEnumerable<I1> enumerableOfI1 = listOfCI1; //this works

IList<I1> listofI1 = listOfCI1; //this does not

I am able to assign my "listOfCI1" to an IEnumerable<I1> (due to covariance)

But why am I not able to assign it to an IList<I1>? For that matter, I cannot even do the following:

List<I1> listOfI12 = listOfCI1;

Shouldn't covariance allow me to assign a derived type to a base type?

like image 405
Raj Rao Avatar asked Oct 27 '10 14:10

Raj Rao


4 Answers

Simply put, IList<T> is not covariant, whereas IEnumerable<T> is. Here's why...

Suppose IList<T> was covariant. The code below is clearly not type-safe... but where would you want the error to be?

IList<Apple> apples = new List<Apple>();
IList<Fruit> fruitBasket = apples;
fruitBasket.Add(new Banana()); // Aargh! Added a Banana to a bunch of Apples!
Apple apple = apples[0]; // This should be okay, but wouldn't be

For lots of detail on variance, see Eric Lippert's blog post series on it, or watch the video of my talk about variance from NDC.

Basically, variance is only ever allowed where it's guaranteed to be safe (and in a representation-preserving way, which is why you can't convert IEnumerable<int> into IEnumerable<object> - the boxing conversion doesn't preserve representation).

like image 100
Jon Skeet Avatar answered Oct 01 '22 11:10

Jon Skeet


Compare declarations (msdn)

public interface IEnumerable<out T> : IEnumerable

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable

you see that magical word out? This means that covariance is on.

like image 27
Andrey Avatar answered Oct 01 '22 09:10

Andrey


No.

Otherwise, you would then be able add a different implementation of I1 to a list that should only contain C1s.

like image 33
SLaks Avatar answered Oct 01 '22 11:10

SLaks


IList<T> interface is not covariant.

like image 35
Andrew Bezzub Avatar answered Oct 01 '22 11:10

Andrew Bezzub