http://www.albahari.com/nutshell/WhatsNewCs4.aspx offers, amongst many other things, a brief history on what has changed over time in C# with regards to covariance. It gives a Jon Skeetesque history lesson. Covariance at its simplest happens when one implicitly upcasts from a child to a parent (at perhaps the hand-in to a method signature), but the more interesting and, yes, painful things to think about have to do with implicitly upcasting collections of children to collections of their parent. You could do this with an array, the de facto go to collection (are there any others before C# 2.0? Session/ViewState perhaps?) before generics in C# 1.0. You could cast an array of Scorpions to an array of Arachnids, but, as Ben Albahari portrays it in this video, this came with significant problems. One could take in an array of Arachnids at a method signature and be opening the door to really be taking in an array of Scorpions. Within the method if one replaces one of the Arachnids with a new Arachnid, in the case of an array of Scorpions being handed in, the method is going to break due to a type mismatch. It is also perfectly compiler-safe to replace one of the Arachnids with a different child type in this method, such as a Spider, but this too invites trouble and run-time blow-ups. To make compiler-safety for generics covariance closer in keeping to run-time reality for generics in the next version of C#, the upcasting of collections was largely forbidden. The only way you can really do it is by way of the where keyword like so:
void Write<T> (List<T> foo) where T : Arachnid
{
foo[0] = (T)(object) new Spider();
As of C# 4.0 there is support for more implicit covariance in generic interfaces such as IEnumerable which allow a collection to be handed in but not significantly doctored up after the fact. The pendulum swung back the other way a little bit.
No comments:
Post a Comment