Я исследую выполнение этого кода С#:
public static void Test<T>(object o) where T : class
{
T t = o as T;
}
Эквивалентный код IL:
.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
Основываясь на этом ответе (ненужный unbox_any), может ли кто-нибудь объяснить мне, какова точная логика Jitter здесь; как именно Jitter решает игнорировать инструкцию unbox_any в данном конкретном случае (теоретически, согласно msdn, исключение NullReferenceException должно генерироваться, когда инструкция isinst возвращает значение null, но на практике этого не происходит!)
Обновить
На основании ответа usr и комментария Ганса, если obj является ссылочным типом, будет вызываться castclass
и, следовательно, NRE не будет.
Но как насчет следующего случая?
static void Test<T>(object o) where T : new()
{
var nullable = o as int?;
if (nullable != null)
//do something
}
Test<int?>(null);
И эквивалентный код IL (частичный):
IL_0001: ldarg.0
IL_0002: isinst valuetype [mscorlib]System.Nullable`1<int32>
IL_0007: unbox.any valuetype [mscorlib]System.Nullable`1<int32>
IL_000c: stloc.0
IL_000d: ldloca.s nullable
IL_000f: call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
IL_0014: stloc.1
IL_0015: ldloc.1
IL_0016: brfalse.s IL_0024
В этом случае его тип значения, так почему NRE не выбрасывается?
public static void Test<T>(T o) where T : class
Поскольку никогда не выбрасывалось исключение времени выполнения. - person Hamlet Hakobyan   schedule 20.12.2015!eeIsValueClass(resolvedToken.hClass)
- person Hans Passant   schedule 20.12.2015