简体   繁体   中英

.NET CIL Call or CallVirt?

如何确定是否需要使用“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:

  • Is the method static ? Then use call .
  • Is the type you are invoking on a value type? Then use 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.)
  • Is the method you are invoking declared virtual or abstract ? Then use callvirt .
  • Are you invoking the method through an interface reference? Then use callvirt .
  • Is the method you are invoking declared 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM