Performing C # polymorphism with generics

I noticed in C #, unlike C ++, you can combine virtual and general 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 Generic<T> versions can be created, it does not look like the standard vtbl method can be used to resolve method calls, but in fact it is not. Here is 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] 

Extra code seems to be looking for dynamic vtbl according to general parameters, and then calls it. Has anyone written about the features of this implementation? How well does it work compared to the non-general case?

+6
performance generics polymorphism c #
source share
2 answers

An implementation of .NET generics can easily handle this scenario and with very good performance. I wrote a blog post about this a while ago.

One of the best resources for finding information on how the CLR implements generics is Micosoft Research's paper .

You have the right to a virtual table. How the CLR creates executable code for a generic type when a JIT compiler stumbles upon it depends on the type parameter. Processing is different for value types and reference types.

While the exectuable code (instance, native image) is shared for instances for all typical type parameters that are reference types, the vtable associated with the instance (object) of the instance is unique to a particular type of parameter.

Here's the corresponding quote from the above article:

4.2 Representation of objects Objects in the CLR garbage heap assembly represented by the vtable pointer and then the contents of objects (for example, fields or array elements). The main role of vtables is the virtual dispatch method: it contains a code pointer for each method that is defined or inherited by the object class. But for simple class types, at least where there is a one-to-one correspondence between vtables and classes, it can also be used to represent type objects. When vtable is used this way, we call it type type handle. In the implementation of polymorphism based on full specialization, the concept of exact execution time is supplied free of charge as different instances of the same parameterized type have different virtual tables. But now suppose the code is shared between various inputs such as List<string> and List<object> . The vtables for the two instances will be identical, so we need a way to represent the instance at runtime.

...

[For each instance, we] Replace the vtable pointer with a pointer to the combined file of the vtable- and-instance structure and duplicate its [structure] per instance.

+3
source share

As the common .NET family trees are implemented, for each use of a generic class (or method), the CLR creates a new implementation of this class (or method) with a common parameter filled in. For reference types, they all share a single implementation (since they are all just pointers of the same size); each of them has its own implementation, since the sizes are all different.

Therefore, I assume that each implementation of the generic type / method also has its own vtable, and this code performs a "generic search implementation" and then "lookup vtable override" in the implementation it finds.

0
source share

All Articles