根据 调用 ToString() 时对结构进行装箱,在 C# 上调用未重写的方法
struct
会导致其被装箱。这最终是因为 constrained callvirt
IL 指令的工作原理,根据 文档,它表示:
如果
是值类型并且thisType
未实现thisType
,则method
将被取消引用、装箱,并作为“this”指针传递给ptr
方法指令。callvirt
但是,它并没有解释为什么会这样,特别是如果
struct
确实实现了该方法,它不会对 struct
进行装箱:
如果
是值类型并且thisType
实现thisType
,则method
将不加修改地作为指向ptr
call
指令的“this”指针传递,以便由method
method
实现thisType
.
为什么即使该方法没有被
struct
实现或覆盖,运行时也不能做同样的事情?这可能与运行时如何调用方法有关,但我无法弄清楚。
简单地说,方法
object.ToString()
是在假设this
将是object
的实例的情况下编写的。 (毕竟,这就是实例方法的工作原理)。你不能向它传递一个指向结构的指针并期望它能够工作。
所有引用类型都有一个对象头和方法表。然而,结构却没有(没有必要)。因此,如果您只是将一个(指向某个)结构体传递给一个需要指向
object
的指针的方法,该方法可能会以令人兴奋和致命的方式崩溃。
当您装箱一个结构体时,它会被复制到堆中,并给出一个对象头和方法表。这就是为什么装箱结构是有效的
object
。因此,调用需要 object
但传递结构的方法的方法是对结构进行装箱。
当您在结构体本身上定义
ToString
的重写时,该方法需要一个指向结构体的指针(并且不假设该指针指向方法表),因此您可以直接传递结构体而无需装箱。