OpCodes.Constrained 字段

定义

约束执行虚拟方法调用的类型。

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

字段值

注解

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

Format 程序集格式 说明
FE 16 <T> 约束。 thisType 对约束为类型 T的类型调用虚拟方法。

constrained仅允许在指令中callvirt使用前缀。

此时 MSIL 堆栈的状态必须如下所示:

  1. 托管指针 ptr被推送到堆栈上。 类型 ptr 必须是托管指针 (&) 到 thisType。 请注意,这与不受支持的 callvirt 指令的情况不同,该指令需要引用 thisType

  2. 方法argN参数arg1被推送到堆栈上,就像使用不受支持的callvirt指令一样。

前缀 constrained 旨在允许 callvirt 以统一方式进行指令,而不受值类型还是引用类型无关 thisType

callvirt method当指令作为constrainedthisType前缀时,该指令将按如下所示执行:

  • 如果thisType引用类型(与值类型相反),则会ptr取消引用并作为指向其methodcallvirt“this”指针传递。

  • 如果thisType为值类型并thisType实现,methodptr作为指令的“this”指针callmethod传递,以供method实现。thisType

  • 如果 thisType 为值类型且 thisType 未实现 method ,则 ptr 取消引用、装箱并作为指向指令的“this”指针 callvirtmethod 传递。

此最后一种情况只能在定义Objectmethod发生,ValueType或者Enum不能被thisType重写。 在这种情况下,装箱会导致创建原始对象的副本。 但是,由于没有方法ObjectValueTypeEnum以及修改对象的状态,因此无法检测到此事实。

前缀 constrained 支持创建泛型代码的 IL 生成器。 通常,指令 callvirt 对值类型无效。 相反,IL 编译器在编译时有效地执行上面概述的“this”转换,具体取决于所调用的方法的类型 ptr 和方法。 但是,如果 ptr 泛型类型在编译时未知,则无法在编译时进行此转换。

constrained操作代码允许 IL 编译器以统一的方式调用虚拟函数,而与值ptr类型还是引用类型无关。 尽管它适用于泛型类型变量的情况 thisTypeconstrained 但前缀也适用于非泛型类型,并可以减少以语言生成虚拟调用的复杂性,这些语言隐藏值类型和引用类型之间的区别。

constrained使用前缀还可以避免值类型的潜在版本控制问题。 constrained如果未使用前缀,则必须发出不同的 IL,具体取决于值类型是否替代 System.Object 的方法。 例如,如果值类型 V 重写 Object.ToString() 方法,则会发出指令 callV.ToString() ;如果没有, box 则会发出指令和 callvirtObject.ToString() 指令。 如果以后删除了替代,则在前一种情况下可能会出现版本控制问题,在后一种情况下,如果添加了替代,则会出现版本控制问题。

constrained前缀还可用于对值类型调用接口方法,因为实现接口方法的值类型方法可以使用 a 更改MethodImplconstrained如果未使用前缀,编译器将强制选择要在编译时绑定到的值类型的方法。 constrained使用前缀,MSIL 可以绑定到在运行时(而不是编译时)实现接口方法的方法。

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

适用于