Не очень чистый IL код получается для вот такого вот случая.
public DefConstUnchecked() : long
{
unchecked
{
def a : uint = 0xAA000000;
def b : uint = 0x00BB0000;
(a + b)
}
}
Получаем:
.method public hidebysig static int64 DefConstUnchecked() cil managed
{
// Code size 18 (0x12)
.maxstack 2
.locals init (uint32 V_0,
uint32 V_1)
IL_0000: ldc.i4 0xaa000000
IL_0005: stloc.0
IL_0006: ldc.i4 0xbb0000
IL_000b: conv.ovf.u4
IL_000c: stloc.1
IL_000d: ldloc.0
IL_000e: ldloc.1
IL_000f: add
IL_0010: conv.ovf.i8.un // (3)
IL_0011: ret
} // end of method Program::DefConstUnchecked
(1) здесь компилятор знает что литерал 0xAA000000 — это uint, собственно без тайп энфорсмента он uint и выводит. OK.
(2) здесь компилятор вывел бы тип int и теперь переносит приведение константы в рантайм, вдобавок делает почему-то через conv.ovf.u4 хотя мы в unchecked контексте.
(3) опять какая-то левая конвертация, тут подошел бы conv.u8.
Вопрос — где бы покопать, что бы это исправить?
Я так понимаю, что выражение просто "вычисляется", а посему и просвечивается факт конвертации типа как есть.
Хотя например при присвоении полю константы — ничего подобного не происходит.
В принципе это жить сильно не мешает, возможно JIT это выбрасывает вообще, а может и не выбрасывает.