OpCodes.Callvirt 字段

定义

对对象调用后期绑定方法,将返回值推送到计算堆栈。

public: static initonly System::Reflection::Emit::OpCode Callvirt;
public static readonly System.Reflection.Emit.OpCode Callvirt;
 staticval mutable Callvirt : System.Reflection.Emit.OpCode
Public Shared ReadOnly Callvirt As OpCode 

字段值

注解

下表列出了指令的十六进制和Microsoft中间语言(MSIL)程序集格式,以及简短的参考摘要:

Format 程序集格式 Description
6F <T> callvirt method 调用与 . 关联的 obj特定方法。

堆栈过渡行为按顺序排列,为:

  1. 对象引用 obj 被推送到堆栈上。

  2. 方法arg1参数argN被推送到堆栈上。

  3. 方法自变量arg1和对象引用argN从堆栈中弹出;使用这些参数执行方法调用,并且控件将传输到方法元数据令牌所引用的方法objobj 完成后,返回值由被调用方方法生成,并发送到调用方。

  4. 返回值被推送到堆栈上。

指令对 callvirt 对象调用后期绑定方法。 也就是说,该方法是根据方法指针中显示的运行时类型 obj 而不是编译时类选择的。 Callvirt 可用于调用虚拟和实例方法。 指令callvirt可能紧接 (tailTailcall) 前缀,以指定在传输控件之前应释放当前堆栈帧。 如果调用将控制权转移到比原始方法更高的信任方法,则堆栈帧将不会释放。

方法元数据令牌提供要调用的方法的名称、类和签名。 与之 obj 关联的类是其实例的类。 如果类定义与指示的方法名称和签名匹配的非静态方法,则调用此方法。 否则,将按顺序检查此类的基类链中的所有类。 如果未找到任何方法,则为错误。

Callvirt 在调用方法之前,将对象和关联的参数从计算堆栈中弹出。 如果方法具有返回值,则该方法在方法完成时将推送到堆栈上。 在被调用方端,该 obj 参数作为参数 0 访问, arg1 作为参数 1 等。

参数按从左到右的顺序放置在堆栈上。 也就是说,计算第一个参数并将其放置在堆栈上,然后是第二个参数,然后是第三个参数,直到所有必需的参数都按降序排列在堆栈上。 实例引用 obj (始终需要 callvirt)必须推送到任何用户可见参数之前。 签名(在元数据令牌中携带)不需要包含此指针的参数列表中的条目。

请注意,也可以使用指令调用 Call 虚拟方法。

MissingMethodException 如果在与其 obj 任何基类关联的类中找不到具有指示名称和签名的非静态方法,则引发 。 当Microsoft中间语言(MSIL)指令转换为本机代码(而不是在运行时)时,通常会检测到这种情况。

如果 obj 为 null,则引发

SecurityException 如果系统安全性未授予调用方对所调用方法的访问权限,将引发 。 当 CIL 转换为本机代码而不是运行时时,可能会进行安全检查。

注释

在值类型上调用 System.Object 的方法时,请考虑将 constrained 前缀与指令一起使用 callvirt 。 这样就无需根据值类型是否重写方法发出不同的 IL,从而避免了潜在的版本控制问题。 考虑在对值类型调用接口方法时使用 constrained 前缀,因为实现接口方法的值类型方法可以使用 a 更改 MethodImpl。 操作代码中 Constrained 更详细地介绍了这些问题。

以下 Emit 方法重载可以使用 callvirt 操作码:

适用于