如果 CIL 仅基于堆栈,为什么它支持实例

Why does CIL support instances if it is solely stack based

在通用中间语言 (CIL) 中,我们可以实例化 类,它们不是静态的。如果我们需要在方法调用之间存储实例数据,那将非常有意义。为什么在一切都位于堆栈上的 CIL 中这是必要的? CIL中没有存储实例数据,为什么需要实例?或者责怪编译器:为什么编译器不将 CIL 中的每个方法都编译为静态的?我最好的猜测是可以从 CIL 中提取更高级别代码的信息。这对于有经验的 CIL 程序员来说可能听起来很愚蠢,因为它可能是完全错误的,但我才刚刚开始接触它。

非常感谢任何澄清。

一个原因是虚拟方法。 CLR 理解虚拟方法,当使用 callvirt 操作码时,它会根据实例的运行时类型调用正确的覆盖。

如果所有方法都是静态的,这是不可能的。 C# 编译器(以及所有其他编译器)必须自己实现虚拟分派,这也会阻止各种去虚拟化优化。

CIL 中隐含的假设是 class 对象存储在 GC 堆上。在运行时也准确。创建对象时返回的是对该对象的引用。一个指针。 32位模式占用4个字节,64位模式占用8个字节

你用那个指针做什么取决于你的代码。您可以将其存储在局部变量中(类似于将其存储在堆栈中),也可以将其存储在字段或静态变量中。在运行时,它与 IntPtr 没有根本区别,只是垃圾收集器总能找到它。当它压缩堆时移动对象是必要的,指针值需要更新。引擎盖下发生了很多魔法来帮助 GC 找到那个指针,即时编译器 plays an essential role.

从运行时的角度来看,所有的方法都是静态的。编写扩展方法时非常明显。 C# 静态方法和实例方法之间的区别在于传递给方法的 extra 隐藏参数。你懂的,就是this。您始终可以在实例方法中使用的关键字。您不必在方法的参数列表中自己命名它,编译器会处理它。您确实在扩展方法中明确命名了它。