.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;
}
我的问题是:
var a = father as child
isinst intruction将调用并且没有unbox.any,并且如果我将删除泛型定义并且尝试将对象强制转换(isinst)到某个类,则不会调用unbox.any。
更新
我可以理解unbox_any因为对象类型参数,它会在isinst检查之后尝试将其转换为具体类型。也许泛型也有影响。
我的问题是,如果我们尝试将其拆箱到T的obj为null,为什么不在unbox.any中引发异常?
文档说:“如果obj为空引用,则抛出NullReferenceException。”
最佳答案
取消包装是为了使验证者满意。对于知道类型参数T始终是引用类型的情况,验证程序不是特别聪明,因此C#编译器会发出这些原本不必要的取消框。
如果在Roslyn源代码中搜索Unbox_any和IsVerifierReference,您会发现这种情况发生在代码生成器周围的很多地方。
抖动会在生成代码时知道type参数是否为引用,并且无论看上去似乎不必要的指令如何,都应该生成体面的代码。