6

I am sure if the Title is explainatory or not, but I need some help understanding the concept.

We have class (reference types) that has method table associated with Type object. In addition to the method tables, the type object also contains all the static fields, type obj pointer and sync block index.

CLR refers to this method table when calling methods on instance of a reference type.

Method table contains the IL for a particular method that is used to change the state of instance fields.

Similarly we can define methods for a structs (value types).

At runtime, when a method is called on a value type, from where does the CLR refer to the IL of the method being called on the instance of the value type.

struct A
{
    // for Immutability of value type
    public readonly int a;

    public void MethodOnValueType()
    {
        // Some code here
    }
}

Where does CLR refer to find the IL for the method named "MethodOnValueType"?

Is there any Type Object for the value type in the managed heap?

I am sure for the case of reference types but confused for value types.

Thanks.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
Dinesh
  • 3,652
  • 2
  • 25
  • 35

2 Answers2

1

Value types have Type objects, just as classes do.

Type intType1 = typeof(int);
Type intType2 = 100.GetType();

Debug.Assert(ReferenceEquals(intType1, intType2));

Dispatch to non-virtual methods is essentially the same for structs as it is for classes.

Virtual methods involve lookups in v-tables, which are a property of reference types. If you declare a struct that defines an interface, then call it via that interface, it will be boxed automatically into a reference type so that this virtual member may be invoked.

Hope that helps somewhat.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • 1
    A detail. Calling `.GetType()` on a value type goes through boxing, and therefore it has "surprising" results for `Nullable<>`. Specifically `(new Nullable(42)).GetType()` will get the type of `Int32` with no nullable wrapping, and `(new Nullable()).GetType()` throws a `NullReferenceException` run-time. – Jeppe Stig Nielsen Dec 23 '12 at 18:08
1

Methods on value-types do not support polymorphism (except for the methods inherited from object, which are executed differently depending on whether they have been overridden): the call is a static call (not a virtual call). Basically, the "what method" part of the call information is resolved by the compiler and burned into the IL. It is then the job of the JIT to connect that call to the final method code.

There is no object-header etc on a value-type.

You can get a Type object for value-types, but that is not really related to method-call.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Sir correct me if i am wrong -> methods on a value type do not support polymorphism because value types are sealed and cannot be derived from. So the virtual methods of Object class are called non virtually by the CLR knowing the fact that the method is called on a value type. But what about the IL of the method that it defined by the struct itself. Where is that stored before at runtime JIT converts them to native code when the method is called on any instance of the struct? – Dinesh Dec 23 '12 at 17:34
  • @Dnsh as IL in the assembly metadata: nothing more than that. The call instruction simply has a token to the method desired - it isn't inlined – Marc Gravell Dec 23 '12 at 18:43
  • @Dnsh also, the choice of static vs sealed vs polymorphism is all inter-related - saying which is the cause and which the consequence is complicated – Marc Gravell Dec 23 '12 at 18:45
  • Hello Sir, when we call GetType method on a value type, why does it need to box the value type before calling that method. Why the compiler does not generate code to directly call the GetType on the value type knowing that it is a value type and no polymorphism can occur? – Dinesh Dec 27 '12 at 19:46
  • @DnshPly9 it is a fair question; indeed, the compiler already knows the type (it needs it in order to construct a box). If I had to guess, it simply isn't something that is defined in the spec, and the compiler is following the spec. Ultimately, though, I guess that cuts two ways: since **you** (at the call-site) clearly know the type, why are **you** calling `.GetType()` ? – Marc Gravell Dec 27 '12 at 20:39
  • lol...true :), one more thing i would like to ask, the address offset generated by compiler (for e.g C compiler), how does the compiler decide what methods to place at what address offset?? is there any alogrithm for that? – Dinesh Dec 27 '12 at 20:48
  • @DnshPly9 I don't even know if it does. Ecma 335 would be the thing to look at. – Marc Gravell Dec 27 '12 at 20:53