考虑这个 IL 片段(由 Microsoft 的 C# 编译器生成):
.class public sequential ansi sealed beforefieldinit Foo
extends [mscorlib]System.ValueType
{ … }
.method private hidebysig static void Main(string[] args) cil managed
{
.maxstack 1
.locals init ([0] valuetype Foo foo)
ldloca.s foo // ?
constrained. Foo // ?
callvirt instance string [mscorlib]System.Object::ToString() // ?
pop
ret
}
我想确切地知道标记的三行中发生了什么// ?
:如何在未装箱的值类型上调用虚拟方法( System.Object
's ) ,(根据 CLI 规范的第 I.8.9.7 节) 根本没有基本类型?ToString
我目前的不完全理解是这样的:
ldloca.s foo
*
产生一个指向局部变量foo
(它包含一个未装箱的类型的值)的临时指针( )valuetype Foo
,在这种情况下,根据 CLI 规范的第 I.12.3.2.1 节,可以在需要托管指针(&
)的地方使用。此
*
指针将充当方法调用的this指针。这似乎是合法的,因为它可以在此处充当托管指针 (&
)。CLI 标准在第 I.8.9.7 节中提到了这种可能性。constrained. Foo
前缀是为了防止将值装箱到valuetype Foo
对象boxed Foo
中。
但主要问题仍然存在:为什么可以在未继承该虚拟方法的未装箱值上调用虚拟方法?