[英].NET CIL Call or CallVirt?
如何确定是否需要使用“Call”或“Callvirt”调用方法?
By default, the C# compiler always uses callvirt for everything except static or value type calls. 默认情况下,C#编译器始终将callvirt用于除静态或值类型调用之外的所有内容。 This causes implicit null checking of the 'this' (arg0) argument.
这会导致对'this'(arg0)参数进行隐式空值检查。 You're not strictly required to follow this convention, but any virtual method on a reference type will definitely require callvirt.
您并不是严格要求遵循此约定,但引用类型上的任何虚拟方法肯定都需要callvirt。
You can follow these simple rules one by one to determine which you should use: 您可以逐个遵循这些简单的规则来确定您应该使用哪些:
static
? static
吗? Then use call
. call
。 call
. call
。 (This does not apply if the value is boxed -- then you are actually invoking on object
or some interface, and those are reference types.) object
或某个界面上调用,而这些是引用类型。) virtual
or abstract
? virtual
还是abstract
? Then use callvirt
. callvirt
。 callvirt
. callvirt
。 override
, but neither the method nor the declaring type declared sealed
? override
,但方法和声明类型都没有声明sealed
? Then use callvirt
. callvirt
。 In all other cases, no virtual dispatch is required so you can use call
-- but you should use callvirt
. 在所有其他情况下,不需要虚拟调度,因此您可以使用
call
- 但您应该使用callvirt
。 Here's why: 原因如下:
Using callvirt
on non-virtual methods is equivalent to call
except when the first argument is null. 在非虚方法上使用
callvirt
等同于call
除非第一个参数为null。 In that case callvirt
will throw a NullReferenceException
immediately, whereas call
will not. 在这种情况下,
callvirt
会立即抛出NullReferenceException
,而call
则不会。 This makes sense, because callvirt
is intended to be used in cases where virtual method dispatch is desired, and you can't do virtual method dispatch if you don't have an object on which to do a vtable lookup. 这是有道理的,因为
callvirt
旨在用于需要虚拟方法调度的情况,如果没有可以进行vtable查找的对象,则无法进行虚拟方法调度。
Note that callvirt
will still throw an exception if the first argument is null even if a vtable lookup isn't necessary! 请注意,即使不需要vtable查找,如果第一个参数为null,
callvirt
仍将抛出异常!
Considering this information, using callvirt
for all non-static method invocations on reference types (as the C# compiler does) may be preferable as it will cause a NullReferenceException
immediately at the call site instead of sometime later when this
gets used (explicitly or implicitly) inside of the method. 考虑到这一信息,使用
callvirt
对引用类型的所有非静态方法调用(如C#编译器)可以是优选的,因为它会导致NullReferenceException
,立即在调用点,而不是一段时间后,当this
被使用(明确或隐含)方法内部。
如果在虚方法的dynamic方法中使用call,则运行时会抛出安全异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.