CIL指令“isinst

发布于 2024-09-16 04:02:59 字数 434 浏览 4 评论 0原文

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

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

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

IL_0001: isinst System.RuntimeTypeHandle

并且 System.RuntimeTypeHandle 是 valuetype。有人可以把我放在这里吗?

The ECMA Common Language Infrastructure documentation says this about the CIL "isinst class" instruction:

Correct CIL ensures that class is a valid typeref or typedef or typespec token indicating a class, and
that obj is always either null or an object reference.

This implies that a valuetype is not allowed, right? But mscorlib.dll contains a method System.RuntimeTypeHandle::Equals(object obj) with the following instruction:

IL_0001: isinst System.RuntimeTypeHandle

And System.RuntimeTypeHandle is a valuetype. Can anybody put me right here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

恬淡成诗 2024-09-23 04:02:59

看一下 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 分配给 ii变成一个int。在下一行中,i被自动装箱到其相应的ReferenceType(类),因此警告是显而易见的。我们甚至可以写下

var b = i is int;

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

Have a look at the declaration of RuntimeTypeHandle:

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

Although RuntimeTypeHandle is declared as a struct its representation in CIL is some kind of special class. In other words, you can imagine structs as special classes that inherit from System.ValueType and whose attributes follow a strict order.

With that in mind isinst would be callable with RuntimeTypeHandle. For what I interpret isinst is not limited to reference types at all as long as there is a class representing the type.

Let's say we write in C#:

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

We get a compiler warning

Warning: The given expression is always of the provided ('int') type.

What happens? We assign 4 to i. ibecoms an int. On the next line iis being auto-boxed to its corresponding ReferenceType (class), so that the warning is obvious. We could even write

var b = i is int;

I hope this can contribute to some kind of clearification on this topic.

晚风撩人 2024-09-23 04:02:59

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

不,但他们的措辞令人困惑。这里的classisinst接受的第二个参数的名称。它是一个标记(可以认为是与类型相关的元数据表之一中的行的索引),表示接口、类或结构(基本上是任何类型) 。

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

如果 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 我们的 valuetype 实例,然后才能传递它。

例如,这个保证具有结构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

PS。
实际上,即使没有通用约束,我们也会进行装箱(参见 这个问题),但这更多地表明 isinst 总是需要对象引用。

This implies that a valuetype is not allowed, right?

No, but they have worded it in a confusing way. class here is the name of second parameter that isinst accepts. It is a token (think an index of a row from one of the Type-related metadata tables) that represents an interface, a class or a struct (basically any Type).

What is a bit hidden is the first parameter that is passed from the stack - the object reference.

If isinst was a C# method it will be something like this:

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

In your example with RuntimeTypeHandle.Equals(object obj) you didn't include the very first line which is passing of the object argument to isinst:

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

The only issue with value types is that from the signature of the "fake" IsInst you'd recognize that we need to box our valuetype instance before we can pass it.

for example this generic method that is guaranteed to have a a struct value:

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

will have boxing code before calling isinst:

IL_0000: ldarg.1
IL_0001: box !!T
IL_0006: isinst [System.Runtime]System.Int32

PS.
Actually we would have boxing even without the generic constraint (see this question), but that goes to show even more that isinst just always requires an object reference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文