.net 如果CIL完全基于堆栈,为什么它支持实例

.net 如果CIL完全基于堆栈,为什么它支持实例,.net,oop,static,instance,cil,.net,Oop,Static,Instance,Cil,在公共中间语言(CIL)中,我们可以实例化非静态的类。如果我们需要在方法调用之间存储实例数据,那么这很有意义。为什么这在CIL中是必要的,因为所有东西都位于堆栈上?CIL中没有存储实例数据,为什么我需要实例?或者责怪编译器:为什么编译器不在CIL中编译每个静态方法?我最好的猜测是,高级代码的信息可以从CIL中提取。对于一个有经验的CIL程序员来说,这可能听起来很愚蠢,因为这可能是完全错误的,但我刚刚开始了解它 任何澄清都非常感谢。一个原因是虚拟方法。CLR理解虚拟方法,当使用callvirt操作

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

任何澄清都非常感谢。

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


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

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

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

从运行时的角度来看,所有方法都是静态的。编写扩展方法时非常明显。C#static方法和实例方法之间的不同之处在于传递给该方法的额外隐藏参数。你很清楚,这是
这个
。在实例方法中始终可以使用的关键字。您不必在方法的参数列表中自己命名它,编译器会处理它。您确实可以在扩展方法中显式地命名它