Reader warning: this session was deep! I take no responsibility for any subtle
inaccuracies I’ve introduced. I’ve missed out some of the most complex stuff to minimise
the risk of error…
Generics are not a new concept; they have been around for many years in other
languages, including C++ (as templates). Generics are commonly used for collections.
In C++, if you create an object such as a Stack<T> and use it as Stack<int>,
Stack<double>, and Stack<point>, the C++ compiler does the work of turning
this into three separate classes. In C#, the compiler doesn’t do this, but instead
this is handled through extensions to the runtime.
In the IL, parameters are represented as !x, where x is the ordinal of the specific
type parameter. IL is of course a stack-based machine. A line such as:
T retval = _array[index];
is represented as:
ldarg.0 ldfld !0 class GenericsDemo.GenericStack<!0>::_array ldloc.0 ldelem !0 stloc.1
Detailed metadata information on the generics can be viewed using MetaInfo (choose
View / MetaInfo). Using this tool, you can view the heap as well as the metadata tables.
The TypeDef table contains the definitions of each generic; you can use this to drill
into the heap and via the string tables identify the various different elements of
the generic. A metadata table GenericParam, for example, can be viewed to see all
the generic types used as parameters.
Each method has a signature. The first byte of every signature highlights the calling
convention (e.g. 20 is an instance method). The remaining bytes highlight the number
of parameters, the return type and the parameter types. So a signature commencing
20 01 01 indicates an instance method with one parameter that returns void. The parameter
types are lookups; for generics, the parameter type is 13 and the parameter number
is then referenced (an ordinal for the generic commencing at 0).
Edit and Continue
As with generics, EnC is an extension to the CLR, rather than a language
feature. It’s up to the specific language to decide which features of EnC to support.
Visual Basic “Whidbey” supports EnC, but even this isn’t a full implementation of
everything that’s available in the CLR. (The C# team have chosen not to support EnC
in the Whidbey release.)
When you make changes at a breakpoint, the debugger creates a separate set of metadata
tables called delta metadata. This contains just the additional or changed metadata.
The debugger also creates delta IL with an RVA (relative virtual address). Other
tables (EnCLog and EnCMap) handle the mapping into the original IL. The CLR then copies
the delta into the original metadata, so that the new code can be found. Once this
has happened, the running state needs to be remapped to ensure that the stack and
registers are still valid.