Search code examples
c#genericsreflectionfunction-pointerscil

C# Generic Object Function Pointers, Same Address?


I'm trying to get the function pointer of a method inside of a generic class. I've been using MethodInfo.MethodHandle.GetFunctionPointer() to do so, but as I've been working with generic classes recently, the above methodology has been working the way I thought it would.

Consider the following:

public class Example<T>
{
    public bool doSomething()
    {
        /*some work*/
        return true;
    }
}

The following all return the same memory address:

typeof(Example<int>).GetMethod("doSomething").MethodHandle.GetFunctionPointer()
typeof(Example<bool>).GetMethod("doSomething").MethodHandle.GetFunctionPointer()
typeof(Example<SomeClass>).GetMethod("doSomething").MethodHandle.GetFunctionPointer()

I'm not sure why this is. Can anyone explain it to me? Is there really only one version of that function within memory?

Surely this raises some eyebrows. I am working on a modifying a game's code without access to the source. Injecting code this way is common practice in this line of work. The EULA for the game specifically allows for such injection as well, so long as the original dll file is not directly modified.


Solution

  • That's because, as stated in this article by Anders Hejlsberg (lead C# architect):

    Now, what we then do is for all type instantiations that are value types—such as List<int>, List<long>, List<double>, List<float>—we create a unique copy of the executable native code. So List<int> gets its own code. List<long> gets its own code. List<float> gets its own code. For all reference types we share the code, because they are representationally identical. It's just pointers.

    In your example, bool and int are value types. They each get their own copy and so they have different pointers to doSomething. SomeClass is reference type (I assume). So it shares its code with other reference types, but not with value types. So it also has different doSomething pointer (different from bool and int versions). If you use another reference type (SomeOtherClass) - it will have the same pointer as SomeClass version of doSomething.