CIL 指令“isinst <valuetype>”

问题描述 投票:0回答:2

ECMA 公共语言基础设施文档对 CIL“isinst class”指令有这样的描述:

正确的 CIL 确保 class 是指示类的有效 typeref 或 typedef 或 typespec 标记,并且 obj 始终为 null 或对象引用。

这意味着不允许使用值类型,对吧?但 mscorlib.dll 包含一个方法 System.RuntimeTypeHandle::Equals(object obj) ,其指令如下:

IL_0001:正在安装 System.RuntimeTypeHandle

而 System.RuntimeTypeHandle 是一个值类型。有人可以把我放在这里吗?

cil
2个回答
3
投票

看看

RuntimeTypeHandle
的声明:

.class public sequential ansi serializable sealed beforefieldinit RuntimeTypeHandle
    extends     System.ValueType
    implements  System.Runtime.Serialization.ISerializable

虽然

RuntimeTypeHandle
被声明为结构体,但它在 CIL 中的表示是某种特殊的类。换句话说,您可以将结构想象为继承自
System.ValueType
且其属性遵循严格顺序的特殊类。

考虑到这一点,

isinst
可以用
RuntimeTypeHandle
来调用。对于我的解释,
isinst
根本不限于引用类型,只要有一个代表该类型的类即可。

假设我们用 C# 编写:

var i = 4;
var b = i is Int32;

我们收到编译器警告

警告:给定的表达式始终是提供的('int')类型。

会发生什么?我们将

4
分配给
i
i
变成了
int
。在下一行中,
i
被自动装箱到其相应的
ReferenceType
(类),以便警告显而易见。我们甚至可以写

var b = i is int;

我希望这有助于澄清这个主题。


0
投票

这意味着不允许使用值类型,对吧?

不,但他们的措辞令人困惑。

class
这里是 isinst 接受的
second
参数的名称。它是一个代表接口、类或结构(基本上是任何 Type)的
令牌
(可以认为是与类型相关的元数据表之一中的行的索引)。

有点隐藏的是从堆栈传递的第一个参数 - 对象引用

如果

isinst
是一个 C# 方法,它将是这样的:

object IsInst (object reference, Type type){
    if(reference.GetType().IsAssignableTo(type)){
        return reference;
    }
    return null;
}

RuntimeTypeHandle.Equals(object obj)
的示例中,您没有包含将对象参数传递给
isinst
的第一行:

IL_0000: ldarg.1 // this is object obj
IL_0001: isinst System.RuntimeTypeHandle

值类型的唯一问题是,从“假”的签名

IsInst
你会认识到我们需要
box
我们的值类型实例才能传递它。

例如,这个通用方法保证有一个结构

value

bool IsInt<T>(T value)
where T : struct {
    if (value is int) {
        return true;
    }
    return false;
}

调用前会有装箱码

isinst
:

IL_0000: ldarg.1
IL_0001: box !!T
IL_0006: isinst [System.Runtime]System.Int32
© www.soinside.com 2019 - 2024. All rights reserved.