CIL unbox_any 指令 - 奇怪的行为
CIL unbox_any instruction - strange behavior
.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) 到某些 class,没有 unbox.any 将被调用。
可能 unbox.any 被调用是因为泛型定义,所以在这种情况下 unbox.any 需要抛出 NullReferenceException 因为 isinst 指令的答案 return null对于这个铸造。参见 unbox_any。如果您尝试 运行 这段代码,您将看到没有抛出任何异常。
更新
我可以理解 unbox_any 因为对象类型参数,它会在 isinst 检查后尝试将其转换为具体类型。也许仿制药也有影响。
我的问题是,如果我们尝试拆箱到 T 的对象为空,为什么不在 unbox.any 中抛出异常?
文档说:"NullReferenceException is thrown if obj is a null reference."
开箱是为了让验证者开心。验证器在知道类型参数 T 始终是引用类型方面并不是特别聪明,因此 C# 编译器会发出这些不必要的拆箱。
如果您在 Roslyn 源代码中搜索 Unbox_any 和 IsVerifierReference,您会发现这种情况发生在代码生成器的很多地方。
抖动会在生成代码时知道类型参数是否是引用,并且应该生成像样的代码而不考虑看似不必要的指令。
.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) 到某些 class,没有 unbox.any 将被调用。
可能 unbox.any 被调用是因为泛型定义,所以在这种情况下 unbox.any 需要抛出 NullReferenceException 因为 isinst 指令的答案 return null对于这个铸造。参见 unbox_any。如果您尝试 运行 这段代码,您将看到没有抛出任何异常。
更新
我可以理解 unbox_any 因为对象类型参数,它会在 isinst 检查后尝试将其转换为具体类型。也许仿制药也有影响。
我的问题是,如果我们尝试拆箱到 T 的对象为空,为什么不在 unbox.any 中抛出异常?
文档说:"NullReferenceException is thrown if obj is a null reference."
开箱是为了让验证者开心。验证器在知道类型参数 T 始终是引用类型方面并不是特别聪明,因此 C# 编译器会发出这些不必要的拆箱。
如果您在 Roslyn 源代码中搜索 Unbox_any 和 IsVerifierReference,您会发现这种情况发生在代码生成器的很多地方。
抖动会在生成代码时知道类型参数是否是引用,并且应该生成像样的代码而不考虑看似不必要的指令。