Visual Studio 2010: Covariance and Contravariance - In search of better examples…
This took me some time to understand even simple examples of covariance and contravariance. If you have great samples, please let me post them.
Email me at bterkaly@microsoft.com (Bruno Terkaly).
Don’t forget to grab the code above.
Here is what I’m running. Are you?
If you haven’t done it yet, please start it now
Yes, to maximize the use of this blog, you should follow along. Learn how to install Visual Studio, then do it.
Click Watch the video to install VS 2010.
Here is some naughty code….
Here is an unfortunate thing. The compiler didn’t catch it, so it hit the runtime. |
Before we start, Here is the class hierarchy of people, employees, etc
|
Test your knowledge: Why doesn’t this compile?
The answer is always the same with compiler writers – “because you can get into trouble…” A parameter is covariant if you can use a more derived type as a substitute for the formal parameter type. So this example is not covariant.It is invariant because you must use the exact match of the formal type name. Object-Based Collections Since .NET 1.x we've struggled with collections (ArrayList, HashTable, Queue and so on). listOfThings could really be Employee objects, and all this code would work.
What about contravariant? A return value is contravariant if you can assign the return type to a variable of a less derived type than the formal parameter. Why isn’t the code above covariant? This code looks like it should succeed because a Employee is type of Person, and one should always be able to assign a more derived type of object, such as a Employee, to a base class reference, such as a Person. This is fixed in C# 4.0. This code should compile in C# 3.0, but does not, because C# currently does not support "Declaration Side Covariance for Interface and Delegate Types," according to Anders Hejlsberg. This is needed because we don't know if we are going to add a "SubContractor," which might also be derived class of a person. Imagine a scenario where you have an array like this: Imagine loop through this array and trying to access the "Salary." Everything works fine until you get to the "SubContractor," where "Hours" and "HourlyRate" are the data elements. We'd get a crash. That is what the type system is protecting us from. |
The C# 4.0 Solution
Bill Wagner’s Excellent Article
https://visualstudiomagazine.com/articles/2009/05/01/generic-covariance-and-contravariance-in-c-40.aspx |