ValueType.GetType()如何确定结构的类型?

时间:2009-05-29 14:44:28

标签: c# .net types

对于引用类型,对象的内存布局为

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

对于值类型,对象布局似乎是

|  Instance fields...|

对于引用类型,GetType表示从“类型对象指针”中查找对象。给定引用类型对象的所有对象都指向同一类型对象(也有方法表)

对于值类型,此指针不可用。那么GetType()如何工作?

我查了一下Google,我找到了这个片段..这有点模糊。有人可以详细说明吗?

  

解决方案是位于   存储的值可能只存储   某种类型的价值观。这是   由验证者保证。   Source

2 个答案:

答案 0 :(得分:25)

在值类型的值类型框上调用GetType()。通过将值类型移动到堆上,您现在拥有一个引用类型,该引用类型现在具有指向该对象类型的指针。

如果你想避免拳击,你可以调用GetTypeCode,它会返回一个枚举,指示值类型的类型,而无需装箱。

这是一个显示发生拳击的示例:

<强> C#:

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

IL 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 
}

编辑:要显示编译器正在执行的操作,请更改文字的类型,如下所示:

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

通过在文字后添加"L"我告诉编译器我希望将这个文字转换为System.Int64。编译器会看到这一点,当它发出box指令时,它看起来像这样:

.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 
}

正如您所看到的,编译器已经完成了确定要发出的正确指令的艰苦工作,之后由CLR来执行它们。

答案 1 :(得分:5)

也许安德鲁·H认为这很明显,并努力让我理解+1。我的灯泡时刻再次来自Jon Skeet ..这次是通过他的书,我碰巧正在阅读......以及答案所在的确切区域。

  • C#是静态类型的。 每个变量都有一个类型,并且在编译时就已知。
  • 无法继承值类型。 因此,VT对象不需要携带额外的类型信息(与Ref Type对象相反,每个对象都有一个对象类型头,因为变量类型和值/对象类型< strong>可能不同。)

考虑下面的代码段。虽然变量类型是BaseRefType,但它指向更专用类型的对象。对于值类型,由于继承是非法的,变量类型对象的类型。

BaseRefType r = new DerivedRefType(); 
ValueType v = new ValueType();

我遗失的部分是子弹#1 <Snipped after J.Skeet's comment since it seems to be wrong>。似乎有一些神奇的东西可以让编译器/运行时知道给定任意变量的'变量类型'。 所以运行时以某种方式知道ob是MyStruct类型,即使VT对象本身没有类型信息。

MyStruct ob = new MyStruct();
ob.WhoAmI();                          // no box ; defined in MyStruct
Console.WriteLine(ob.GetHashCode());  // no box ; overridden in ValueType
Console.WriteLine( ob.GetType() );    // box ; implemented in Object

由于这个原因,我能够调用MyStruct(和ValueType中出于某种原因)定义的方法,而无需装箱到RefType。