Reputation: 9138
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?
Upvotes: 15
Views: 975
Reputation: 1500485
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).
Upvotes: 24
Reputation: 60065
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.
Upvotes: 5
Reputation: 887413
No.
Otherwise, you would then be able add a different implementation of I1
to a list that should only contain C1
s.
Upvotes: 3