最近开始沉下心来重新研究C#,看到关于CLR如何调用方法感觉很有意思。
CLR(Common Language Runtime)提供了两个指令来调用方法:
- call 这个IL指令假定变量不为null
- callvirt 使用这个IL指令,编译这个调用时,JIT编译器会生成代码来验证变量是不是null,如果是,callvirt指令会造成CLR抛出NullReferenceException异常
由于callvirt指令会校验null,因此执行速度会比call慢。书中提到callvirt可调用实例方法和虚方法(virtual标识方法,可以被子类重写),不能调用静态方法。但是在C#中实例方法也会使用call指令,对于这一点,书中解释说是因为C#团队认为,JIT编译器应生成代码来验证发出调用的对象不为null。
//callvirt指令调用测试代码
public sealed class CallVirtTest
{
public Int32 GetFive()
{
return 5;
}
public static void Main()
{
CallVirtTest p = null;
Int32 x = p.GetFive();//C#抛出NullReferenceException异常 虽然GetFive方法没有使用任何实参
}
}
虽然C#编译器生成的是callvirt指令,但JIT编译器将优化调用。调用速度主要区别于虚方法与非虚方法。
本内容源自CLR via C#第6章 6.6.1CLR如何调用虚方法,属性和事件的理解,如有理解不正确的还请指正,感谢~