I noticed in C#, unlike C++, you can combine virtual and generic methods. For example:
using System.Diagnostics;
class Base {
public virtual void Concrete() {Debug.WriteLine("base concrete");}
public virtual void Generic<T>() {Debug.WriteLine("base generic");}
}
class Derived : Base {
public override void Concrete() {Debug.WriteLine("derived concrete");}
public override void Generic<T>() {Debug.WriteLine("derived generic");}
}
class App {
static void Main() {
Base x = new Derived();
x.Concrete();
x.Generic<PerformanceCounter>();
}
}
Given that any number of versions of Generic<T> could be instantiated, it doesn’t look like the standard vtbl approach could be used to resolve method calls, and in fact it’s not. Here’s the generated code:
x.Concrete();
mov ecx,dword ptr [ebp-8]
mov eax,dword ptr [ecx]
call dword ptr [eax+38h]
x.Generic<PerformanceCounter>();
push 989A38h
mov ecx,dword ptr [ebp-8]
mov edx,989914h
call 76A874F1
mov dword ptr [ebp-4],eax
mov ecx,dword ptr [ebp-8]
call dword ptr [ebp-4]
The extra code appears to be looking up a dynamic vtbl according to the generic parameters, and then calling into it. Has anyone written about the specifics of this implementation? How well does it perform compared to the non-generic case?
The .NET generics implementation can handle such a scenario easily and with very good performance. I have written a blog post about it a while ago.
One of the best resources for finding information about the how the CLR implements generics is this paper by Micosoft Research.
You got the thing about the vtable right. How the CLR creates executable code for a generic type when the JIT compiler stumbles upon one, depends on the generic type parameter. The handling is different for value types and reference types.
While the exectuable code (instantiation, the native image) is shared among instantiations for all generic type parameters that are reference types, the vtable associated with an instance (object) of the instantiation is unique to the concrete parameter type.
Here’s the relevant quote from the above mentioned paper:
…