Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
320 views
in Technique[技术] by (71.8m points)

c# - How is ValueType.GetType() able to determine the type of the struct?

For a reference type, the object's memory layout is

| Type Object pointer|
|    Sync Block      |
|  Instance fields...|

For a value type, the object layout seems to be

|  Instance fields...|

For a reference type, GetType means find the object from the 'Type Object pointer'. All objects of a given reference type object point to the same type object (which also has the method table)

For a value type, this pointer isn't available. So how does GetType() work ?

I checked with Google and I found this snippet.. which is a bit hazy. Can someone elaborate?

The solution is that the location in which a value is stored may only store values of a certain type. This is guaranteed by the verifier. Source

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Calling GetType() on a value type boxes that value type. By moving the value type onto the heap you now have a reference type which now has a pointer to the type of that object.

If you wish to avoid boxing you can call GetTypeCode which returns an enumeration that indicates the type of the value type without boxing it.

Here is an example showing the boxing that takes place:

C#:

class Program
{
    static void Main()
    {
        34.GetType();
    }
}

IL for Main():

.method private hidebysig static void Main() cil managed
{
        .entrypoint
        .maxstack 8
        L_0000: ldc.i4.s 0x22
        L_0002: box int32
        L_0007: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
        L_000c: pop 
        L_000d: ret 
}

Edit: To show what the compiler is doing, lets change the type of the literal like this:

class Program
{
    static void Main()
    {
        34L.GetType();
    }
}

By adding the "L" after the literal I am telling the compiler that I want this literal to be converted to a System.Int64. The compiler sees this and when it emits the box instruction it looks like this:

.method private hidebysig static void Main() cil managed
{
        .entrypoint
        .maxstack 8
        L_0000: ldc.i4.s 0x22
        L_0002: conv.i8 
        L_0003: box int64
        L_0008: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
        L_000d: pop 
        L_000e: ret 
}

As you can see, the compiler has done the hard work of determining the correct instructions to emit, after that it is up to the CLR to execute them.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...