[英].NET CIL Call or CallVirt?
如何确定是否需要使用“Call”或“Callvirt”调用方法?
默认情况下,C#编译器始终将callvirt用于除静态或值类型调用之外的所有内容。 这会导致对'this'(arg0)参数进行隐式空值检查。 您并不是严格要求遵循此约定,但引用类型上的任何虚拟方法肯定都需要callvirt。
您可以逐个遵循这些简单的规则来确定您应该使用哪些:
static
吗? 然后使用call
。 call
。 (如果值被装箱,则不适用 - 那么您实际上是在object
或某个界面上调用,而这些是引用类型。) virtual
还是abstract
? 然后使用callvirt
。 callvirt
。 override
,但方法和声明类型都没有声明sealed
? 然后使用callvirt
。 在所有其他情况下,不需要虚拟调度,因此您可以使用call
- 但您应该使用callvirt
。 原因如下:
在非虚方法上使用callvirt
等同于call
除非第一个参数为null。 在这种情况下, callvirt
会立即抛出NullReferenceException
,而call
则不会。 这是有道理的,因为callvirt
旨在用于需要虚拟方法调度的情况,如果没有可以进行vtable查找的对象,则无法进行虚拟方法调度。
请注意,即使不需要vtable查找,如果第一个参数为null, callvirt
仍将抛出异常!
考虑到这一信息,使用callvirt
对引用类型的所有非静态方法调用(如C#编译器)可以是优选的,因为它会导致NullReferenceException
,立即在调用点,而不是一段时间后,当this
被使用(明确或隐含)方法内部。
如果在虚方法的dynamic方法中使用call,则运行时会抛出安全异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.