我正在调查这个C#代码的执行情况:
public static void Test(object o) where T : class { T t = o as T; }
等效的IL代码是:
.method public static void Test(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
根据这个答案(不必要的unbox_any),任何人都可以向我解释一下Jitter在这里做的确切逻辑; 在这个特定的情况下,抖动究竟是如何决定忽略'unbox_any'指令的(理论上,根据msdn,当isinst指令产生null时应该抛出NullReferenceException,但这在实践中不会发生!)
更新
基于usr回答和Hans注释,如果obj是引用类型,castclass
将被调用,因此,没有NRE.
但是下面这个案子呢?
static void Test(object o) where T : new() { var nullable = o as int?; if (nullable != null) //do something } Test (null);
和等效的IL代码(部分):
IL_0001: ldarg.0 IL_0002: isinst valuetype [mscorlib]System.Nullable`1IL_0007: unbox.any valuetype [mscorlib]System.Nullable`1 IL_000c: stloc.0 IL_000d: ldloca.s nullable IL_000f: call instance bool valuetype [mscorlib]System.Nullable`1 ::get_HasValue() IL_0014: stloc.1 IL_0015: ldloc.1 IL_0016: brfalse.s IL_0024
在这种情况下它的值类型为什么不抛出NRE?