gpt4 book ai didi

.net - CIL unbox_any 指令 - 奇怪的行为

转载 作者:行者123 更新时间:2023-12-03 09:30:16 25 4
gpt4 key购买 nike

.method public static void  Test<class T>(object A_0) cil managed
{
// Code size 13 (0xd)
.maxstack 1
.locals init (!!T V_0)
IL_0000: ldarg.0
IL_0001: isinst !!T
IL_0006: unbox.any !!T
IL_000b: stloc.0
IL_000c: ret
} // end of method DemoType::Test

相同的 C# 代码是:
public static void Test<T>(object o) where T : class
{
T t = o as T;
}

我的问题是:
  • 为什么 unbox.any 被调用?如果你只是这样做
     var a = father as child 

    isinst 指令将调用并且没有 unbox.any,并且如果我将删除通用定义并且我将尝试将对象强制转换(isinst)到某个类,则不会调用 unbox.any。
  • 也许 unbox.any 被调用是因为泛型定义,所以在这种情况下, unbox.any 需要抛出 NullReferenceException 因为 isinst 指令的答案为此转换返回 null。见 unbox_any .如果您尝试运行此代码,您将看到没有抛出异常。

  • 更新

    我可以理解 unbox_any 因为对象类型参数,它尝试在 isinst 检查后将其转换为具体类型。也许泛型也有影响。

    我的问题是,如果我们尝试拆箱到 T 的 obj 为空,为什么不在 unbox.any 中抛出异常?

    文档说:“如果 obj 是空引用,则抛出 NullReferenceException。”

    最佳答案

    拆箱是为了让验证者开心。验证器在知道类型参数 T 始终是引用类型方面并不是特别聪明,因此 C# 编译器会发出这些不必要的拆箱。

    如果您搜索 Unbox_any 和 IsVerifierReference 的 Roslyn 源代码,您会发现这种情况发生在代码生成器的很多地方。

    抖动会在生成代码时知道类型参数是否是引用,并且应该生成合适的代码,而不管看似不必要的指令。

    关于.net - CIL unbox_any 指令 - 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34318423/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com