Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the c# language prevent generics from being covarient unless they contain no methods that require T as an input?

I have been reading up on the changes that .NET4.5 will bring, and on this blog post I stumbled upon something I neither knew nor understood.

When talking about the implementation of readonly collections, Immo Landwerth says:

Unfortunately, our type system doesn’t allow making types of T covariant unless it has no methods that take T as an input. Therefore, we can’t add an IndexOf method to IReadOnlyList. We believe this is a small sacrifice compared to not having support for covariance.

From my obviously limited understanding, it seems like he is saying that in order to enable us to call a method that requires an IReadOnlyList<Shape> by passing in a IReadOnlyList<Circle>, we can't have a IReadOnlyList<T>.IndexOf(T someShape) method.

I don't see how the type system would prevent that. Can someone explain?

like image 880
Jason Ridge Avatar asked Jun 18 '12 12:06

Jason Ridge


1 Answers

Suppose Circle implements IEquatable<Circle>. That would naturally be used by IReadOnlyList<Circle>.IndexOf if it were available. Now if you could write this:

IReadOnlyList<Circle> circles = ...;
IReadOnlyList<Shape> shapes = circles;
int index = shapes.IndexOf(new Square(10));

that would end up trying to pass a Square to Circle.Equals(Circle) which would clearly be a bad idea.

The rules which enforce the "no values of T in input positions" are in section 13.1.3 of the C# 4 spec. You should also read Eric Lippert's blog series on generic variance for a lot more details.

like image 97
Jon Skeet Avatar answered Oct 11 '22 12:10

Jon Skeet