为什么调用未重写的结构方法需要装箱?

问题描述 投票:0回答:1

根据 调用 ToString() 时对结构进行装箱,在 C# 上调用未重写的方法

struct
会导致其被装箱。这最终是因为
constrained callvirt
IL 指令的工作原理,根据 文档,它表示:

如果

thisType
是值类型并且
thisType
未实现
method
,则
ptr
将被取消引用、装箱,并作为“this”指针传递给
callvirt
方法指令。

但是,它并没有解释为什么会这样,特别是如果

struct
确实实现了该方法,它不会对
struct
进行装箱:

如果

thisType
是值类型并且
thisType
实现
method
,则
ptr
将不加修改地作为指向
call
method
指令的“this”指针传递,以便由
method 实现 
thisType
 
.

为什么即使该方法没有被

struct
实现或覆盖,运行时也不能做同样的事情?这可能与运行时如何调用方法有关,但我无法弄清楚。

c# struct overriding cil boxing
1个回答
1
投票

简单地说,方法

object.ToString()
是在假设
this
将是
object
的实例的情况下编写的。 (毕竟,这就是实例方法的工作原理)。你不能向它传递一个指向结构的指针并期望它能够工作。

所有引用类型都有一个对象头和方法表。然而,结构却没有(没有必要)。因此,如果您只是将一个(指向某个)结构体传递给一个需要指向

object
的指针的方法,该方法可能会以令人兴奋和致命的方式崩溃。

当您装箱一个结构体时,它会被复制到堆中,并给出一个对象头和方法表。这就是为什么装箱结构是有效的

object
。因此,调用需要
object
但传递结构的方法的方法是对结构进行装箱。

当您在结构体本身上定义

ToString
的重写时,该方法需要一个指向结构体的指针(并且不假设该指针指向方法表),因此您可以直接传递结构体而无需装箱。

© www.soinside.com 2019 - 2024. All rights reserved.