Generics : List

List<Dog> is a subtype of List<? extends Animal>, but not a subtype of List<Animal>. Why is List<Dog> not a subtype of List<Animal>? Consider the following example: void mySub(List<Animal> myList) { myList.add(new Cat()); } If you were allowed to pass a List<Dog> to this function, you would get a run-time error. EDIT: Now, if we use … Read more

Covariance and IList

Update: from .NET 4.5 onwards there is IReadOnlyList<out T> and IReadOnlyCollection<out T> which are both covariant; The latter is basically IEnumerable<out T> plus Count; the former adds T this[int index] {get;}. It should also be noted that IEnumerable<out T> is covariant from .NET 4.0 onwards. Both List<T> and ReadOnlyCollection<T> (via List<T>.AsReadOnly()) implement both of these. … Read more

Why aren’t there many discussions about co- and contra-variance in Haskell (as opposed to Scala or C#)?

There are two main reasons: Haskell lacks an inherent notion of subtyping, so in general variance is less relevant. Contravariance mostly appears where mutability is involved, so most data types in Haskell would simply be covariant and there’d be little value to distinguishing that explicitly. However, the concepts do apply–for instance, the lifting operation performed … Read more

Difference between covariance and upcasting

Now, to my untrained eye, covariance seems to be the same as upcasting, except that it refers the casting of collections. (And of a similar statement can be made regarding contravariance and downcasting). Is it really that simple? Covariance isn’t about upcasting, although I can see why you think it’s related. Covariance is about the … Read more

IDictionary in .NET 4 not covariant

It’s a feature. .NET 4.0 only supports safe covariance. The cast you mentioned is potentially dangerous as you could add a non-string element to the dictionary if that was possible: IDictionary<string, object> myDict = new Dictionary<string, string>(); myDict[“hello”] = 5; // not an string On the other hand, IEnumerable<T> is a read-only interface. The T … Read more

C# variance problem: Assigning List as List

Well this certainly won’t be supported in C# 4. There’s a fundamental problem: List<Giraffe> giraffes = new List<Giraffe>(); giraffes.Add(new Giraffe()); List<Animal> animals = giraffes; animals.Add(new Lion()); // Aargh! Keep giraffes safe: just say no to unsafe variance. The array version works because arrays do support reference type variance, with execution time checking. The point of … Read more