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

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

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

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

 | Instance fields...| 

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

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

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

解决方案是存储值的位置可以仅存储特定类型的值。 这由validation者保证。 资源

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

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

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

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 } 

编辑:要显示编译器正在做什么,让我们改变文字的类型,如下所示:

 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执行它们。

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

  • C#是静态类型的。 每个变量都有一个类型 ,它在编译时就已知。
  • 值类型不能inheritance。 因此,VT对象不需要携带额外的类型信息 (与Ref Type对象相反,每个对象具有对象类型标题,因为变量类型和值/对象类型可能不同。)

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

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

我遗失的部分是子弹#1。
。 似乎有一些魔力可以让编译器/运行时知道给定任意变量的’变量类型’。 因此运行时以某种方式知道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。