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 IEnume开发者_Go百科rable<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?
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).
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.
No.
Otherwise, you would then be able add a different implementation of I1
to a list that should only contain C1
s.
IList<T>
interface is not covariant.
精彩评论