Chris Donnan : Programming - Brooklyn Style
software, trading, family, fun
Posted c#, programming on Saturday, February 3rd, 2007.
I spent several months doing .net 2.0 work, then, several months back to a 1.1 project. We have just moved our 1.1 project from nant to msbuild. I am a fan of msbuild, custom tasks and such - it seems like a total better solution than our nant solution. When you have complex work to do - it can get ugly fast - but it seems less ugly with msbuild. In any case - now that that project has been upgraded - I am back the past few weeks to .net 2.0. I really missed anon-delegates more than anything else. Closures are powerful, iterators rock, generics - yes - nice. All of that said - there is at least one glaring problem with generics as implemented in the current CLR.
Generics currently lack covariance/ contravariance
While delegates currently support co/contra variance - generics still lack this behavior. As someone who spends a lot of time building and co-evolving frameworks - this has proven to be troublesome for projects. This is something that irked me ~7-10 months ago and it is back to irritate me again.
Allow me to illustrate…
ArrayList< Car > = new ArrayList< Car >();Â
This is the easiest - no magic at all - same type on each side of the “=” and same type parameter. Of course - this works fine.
Next
IList< Car > = new ArrayList< Car >();Â
Of course this works - this is normal stuff; the inheritance/ implementation of the ‘left side’ of the generic instance declarations work fine (meaning IList/ ArrayList work fine). IList - sure ArrayList implements that - we are good. They also both have a type parameter of type Car - this is fine, we are good to go.
How about this:
IList< Car > = new ArrayList< Ferrari >();Â
In this example lets say Ferrari extends Car. Alas - this does not work. The inheritance/ implementation of the ‘left side’ of the equation (IList/ ArrayList) works fine - but the inheritance on the ‘right side’ of the equation (Car/ Ferrari) DOES NOT WORK. The inheritance scheme does not matter - they are not THE SAME TYPE. This is the ‘crux of the biscuit’ as they say. This is the problem I am talking about :).
Alas -
ArrayList< Car > = new ArrayList< Ferrari >();Â
This does not fix the issue - same problem - even though there is now no inheritance on the ‘left side’ of the equation - and there is simple inheritance on the rights side - it does not matter. The inheritance on the ‘right side’ of the equation does not work in CLR 2.0. Generic types are invariant unfortunately.
This article has an interesting idea on a potential syntax to denote allowed co/contravariant. The idea is that you can use a + or a - in the generic type declaration to denote desired co/contravariant behavior.
Anyhow - there is my complaint rant on generics. I would rather have them as is today than not at all - that is for sure
-Chris
PS - I did not point it out earlier - but all co/contravariance mean is: in one case - your supplied class is a sub-class of the type parameter, in the other case - a super-class of the type parameter.
PPSÂ - Another issue - the new constraint does not allow new(args) to enforce that the template type allows a specific constructor - also annoying!
Comment on this post below
You must be logged in to post a comment.
You can leave a response, or trackback from your own site.















