值 0 (int32) 的 CIL 指令 "isinst [System.Runtime]System.Int32" - return 会是什么?

CIL instruction "isinst [System.Runtime]System.Int32" for value 0 (int32) - what will return?

我有一个简单的 C# 函数

public bool Isinst_intSimple(object value)
{
    return value is int;
}

符合预期Isinst_intSimple(0) returns true

反编译后的函数如下:

IL_0000: nop
IL_0001: ldarg.1      // 'value'
IL_0002: isinst       [System.Runtime]System.Int32
IL_0007: ldnull
IL_0008: cgt.un
IL_000a: stloc.0      // V_0
IL_000b: br.s         IL_000d

// [196 9 - 196 10]
IL_000d: ldloc.0      // V_0
IL_000e: ret

IL_0002 isinst [System.Runtime]System.Int32指令在执行后(输入为0(int32))将什么压入计算栈?

根据 MS 文档,Isinst 指令应该 return 对象引用 - The result (either an object reference or a null reference) is pushed onto the stack.

但是0的引用是什么?而如果。指令IL_0008: cgt.un应该做什么?

我的解读

在我对所有IL指令的解释中——函数重新运行0。而且我找不到 return true.

的方法

下面是我对函数执行的解读:

 IL_0000: nop
IL_0001: ldarg.1      // push 0 on evaluation stack – stack after {0}
IL_0002: isinst       [System.Runtime]System.Int32    //pop and object reference is pushed onto the stack. - stack after { 0* or reference to 0 – boxing? }
IL_0007: ldnull //– stack after {null, 0*}
IL_0008: cgt.un //– 0* is not greater than null so its return 0 -  stack after {0}
IL_000a: stloc.0      // V_0 – pop to V_0 – stack after {}
IL_000b: br.s         IL_000d // – stack after {}

// [196 9 - 196 10]
IL_000d: ldloc.0      // V_0 //– push V_0 – stack after {0}
IL_000e: ret    //return {0}

我认为问题出在IL_0002: isinstIL_0008: cgt.un,但我找不到。

背景

我正在使用模拟 C# dll 的虚拟机 - 逐条指令(在“虚拟机”中执行 C#),但我在模拟测试函数时遇到问题 Isinst_intSimple(0)。我的版本 return 0 但它应该 return true

ECMA-335 specification,它定义了 IL 字节码,表示如下:

I.12.1.6.2.6 castclass and isinst on value types

Casting to and from value type instances isn’t permitted (the equivalent operations arebox and unbox). When boxed, however, it is possible to use the isinst instruction to see whether a value of type System.Object is the boxed representation of a particular class.

III.4.6 - isinst

Test if obj is an instance of typeTok, returning null or an instance of that class or interface.

Stack Transition: ..., obj => ..., result

Description: typeTok is a metadata token (a typeref, typedef or typespec), indicating the desired class. If typeTok is a non-nullable value type or a generic parameter type it is interpreted as “boxed” typeTok

Verifiability: Verification tracks the type of result as typeTok.

因此 isinst 在值类型(结构)上的结果是值的装箱 ObjectRef。

II.1.5 Operand type table

cgt.un is allowed and verifiable on ObjectRefs (O). This is commonly used when comparing an ObjectRef with null (there is no “compare-not-equal” instruction, which would otherwise be a more obvious solution)

所以 isinst ldnull cgt.un 会告诉你对象是否属于特定类型