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)