使用英语阅读

通过


OpCodes.Callvirt 字段

定义

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

public static readonly System.Reflection.Emit.OpCode Callvirt;

字段值

注解

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

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

堆栈过渡行为(按顺序排列)是:

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

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

  3. 通过 argN 和 对象引用obj的方法参数arg1从堆栈中弹出;方法调用是使用这些参数执行的,控件将传输到方法元数据标记引用的方法obj。 完成后,被调用方方法生成一个返回值,并将其发送给调用方。

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

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

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

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

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

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

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

NullReferenceException 如果 obj 为 null,则引发 。

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

备注

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

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

适用于

产品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9, 10
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 2.0, 2.1
UWP 10.0