《CLR via C#》中是这样描述它们的:
编译器在生成方法时会在方法定义表中写入该方法的记录项,每个记录项中有一组标志指令方法是静态方法、实例方法还是虚方法,如下图:
生成IL代码时,编译器会根据这些标志,判断应如何生成IL代码(是使用call还是callvirt)。
call (静态/前期绑定)
该IL指令可调用静态方法、实例方法和虚方法。用call指令调用静态方法,必须指定方法的定义类型。用call指令调用实例方法或虚方法,必须指定引用了对象的变量。call指令假定该变量不为null(在用call指令调用实例和虚方法时,JIT会假定变量不为null,不会生成代码来验证该变量的值是否为null)。换言之,变量本身的类型指明了方法的定义类型。如果变量的类型没有定义该方法,就检查基类型来查找匹配方法。call指令经常用于以非虚方式调用虚方法(意思是如果子类重写的基类的方法,而变量是基类,那么调用的便是基类中该方法的实现,而不是子类中该方法的实现)。请看下面:
首先实现了两个类Animal,Dog继承自Animal并重写了GetName方法。