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 

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

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

  • 方法参数 arg1``argN 被推送到堆栈上,就像使用未采用的 callvirt 指令一样。

    constrained 前缀旨在允许 callvirt 以统一方式进行指令,与值 thisType 类型或引用类型无关。

    callvirt method 当指令具有前缀 constrained``thisType 时,该指令将按如下所示执行:

  • 如果 thisType 引用类型 (而不是值类型) 则 ptr 取消引用并作为指向其的 method “this”指针 callvirt 传递。

  • 如果 thisType 为值类型并 thisType 实现, method 则会 ptr 将未修改为指向指令的“this”指针 call``method 传递,以供其 thisType 实现 method

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

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

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

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

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

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

    以下 Emit 方法重载可以使用 constrained opcode:

  • ILGenerator.Emit(OpCode, Type)
  •