如何确定是否需要使用“Call”或“Callvirt”调用方法?
By default, the C# compiler always uses callvirt for everything except static or value type calls. This causes implicit null checking of the 'this' (arg0) argument. You're not strictly required to follow this convention, but any virtual method on a reference type will definitely require callvirt.
You can follow these simple rules one by one to determine which you should use:
static
? Then use 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.) virtual
or abstract
? Then use callvirt
. callvirt
. override
, but neither the method nor the declaring type declared sealed
? Then use callvirt
. In all other cases, no virtual dispatch is required so you can use call
-- but you should use callvirt
. Here's why:
Using callvirt
on non-virtual methods is equivalent to call
except when the first argument is null. In that case callvirt
will throw a NullReferenceException
immediately, whereas call
will not. 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.
Note that callvirt
will still throw an exception if the first argument is null even if a vtable lookup isn't necessary!
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.
如果在虚方法的dynamic方法中使用call,则运行时会抛出安全异常。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.