Update: In .NET 4.0 the CLR added covariance and contravariance, and the BCL has been updated to use this.
I just finished reading the series of ten blog posts by Eric Lippert about covariance and contravariance. These topics were new to me but after reading this blog series it all made sense. It finally explained to me why some things which I thought I should be able to do does not work in C#.
One example of this is assigning collection to each other. For example look at this code:
IEnumerable<String> strings = new List<String> { “sttt” }; IEnumerable<Object> objects = strings;
This code will cause the compile time error:
“Cannot implicitly convert type ‘System.Collections.Generic.IEnumerable’ to ‘System.Collections.Generic.IEnumerable’. An explicit conversion exists (are you missing a cast?) at line 2 column 31 ”
Although the code makes logical sense it wont work. After reading Lippert’s blog series I can now explain way. Interfaces in C# are NOT covariant on their generic type parameters. This means that even though you can assign a String to an Object, you cannot assign Interface<String> into Interface<Object>. In order to do so you would need to allow the programmer to specify when he wanted variance since many times this behavior is not desired.
For example if the type argument is used as a both a function parameter and a return value in the interface then you want it to be invariant.
This is just a taste of what is described in the blog series so I encourage you to go read and enjoy!.