A genealogy tour in .NET: grandmother.

February 15, 2009 17:13
To bring up a lady, start from her grandmother.
Eric Berne.

Perhaps not a precise citation, but you get the idea. People take their habits and attitudes from their parents, while the parents imitate their own parents and so on. Inexplicably, this sort of upbringing can be
retraced in C# as well.

Far-fetched? Not more than anything else you'd try to compare to software development.

So, here goes Granny!

R
emember generics of .NET 2.0? This cool concept of type parameters that allowed us to design classes and methods without being explicit about the types they use. We started to write highly abstract code, specifying the real type arguments only where it was needed.

A lot of stuff has been said on that topic, so I wouldn’t reiterate and just mention some interesting points.

Implementation.

Implementation of generics in the CLR uses both code sharing (common code for all instantiations) and
code specialization (custom code for each instantiation). Thus, we have a a single copy of the native code for all reference types, but a separate copy of the native code for each value type[1]:
  but      

All reference types such as Cup<string> or Cup<object> will use the same IL code, because at the native code level, references are just pointers with the same representation. But Cup<DateTime> and Cup<int> will have different IL.

The story of the tick sign.

To distinguish between generic types that share the same name but have different type parameters, the compiler adds the number of parameters after the tick sign (`):
 



And this tick sign always reminds me a story that Joel Pobar once shared at DotNetRocks! radio show[2].

In one of the very first releases of generics, the IL generated for a generic type used to have the exclamation mark instead of the tick. Thus, Foo<T> was translated to Foo!1 and Foo<K,V> ended up as Foo!2 and so on. After having the stuff merged out,
in a couple of months the CLR team got a call from Windows debugger guys. It turned out that the recent integration was completely screwed up.

Jeepers! Completely screwed up!

All the tests were broken, and this bang sign was the culprit: Windows debuggers have it reserved as a module delimiter! That means when you started debugging generics, a step at Cup<T> would lead the debugger to a (false) conclusion that the type was in some module, and boom - Windows build is broken.

So the next release of generics came out with the tick sign.

Generic types do not share static fields.

Well, this is sort of well known but anyway: each closed generic type gets its own set of static variables. Said that, it should be easy to tell what – and why – will be printed

class Cup<T> 
{ 
    public static int X = 0; 
    public static void Write() { Console.Write(X); }
}
 
class Test
{
    static void Main()
    {
        Cup<int>.Write();
        Cup<string>.Write();
 
        Cup<int>.X = 5;
 
        Cup<int>.Write();
        Cup<string>.Write();
    }
}

Anything else?

Am I missing anything? Is there anything you find particularly interesting about generics? Your turn now! :)



Footnotes.

[1] – There's a good paper from Andrew Kennedy and Don Syme about design and implementation of .NET generics.

[2] – Amazing DotNetRocks! show #127 with Joel Pobar and Brad Abrams.


Comments are closed