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

时间:2016-10-14 06:45:24

标签: .net oop static instance cil

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

非常感谢任何澄清。

2 个答案:

答案 0 :(得分:4)

CIL中的隐含假设是类对象存储在GC堆上。在运行时也是准确的。创建对象时得到的是对象的引用。一个指针。它在32位模式下需要4个字节,在64位模式下需要8个字节。

使用该指针执行的操作取决于您的代码。您可以将其存储在局部变量中(类似于将其存储在堆栈中),也可以将其存储在字段或静态变量中。在运行时,它与IntPtr没有根本的区别,除了垃圾收集器总能找回它。当对象压缩堆时移动对象时,需要更新指针值。很多魔法发生在幕后帮助GC找回指针,即时编译器plays an essential role

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

答案 1 :(得分:3)

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

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