简单的好奇心,这段代码
private const long constLong = 16;
private static long instanceLong = 16;
static long constTest()
{
long i = 4;
return i + constLong;
}
static long instanceTest()
{
long i = 4;
return i + instanceLong;
}
产生这个IL:
.field private static literal int64 constLong = int64(16)
.field private static int64 instanceLong
.method private hidebysig static int64 constTest () cil managed
{
// Method begins at RVA 0x2068
// Code size 9 (0x9)
.maxstack 2
.locals init (
[0] int64 i
)
IL_0000: ldc.i4.4
IL_0001: conv.i8
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldc.i4.s 16
IL_0006: conv.i8
IL_0007: add
IL_0008: ret
} // end of method Program::constTest
.method private hidebysig static int64 instanceTest () cil managed
{
// Method begins at RVA 0x2080
// Code size 11 (0xb)
.maxstack 2
.locals init (
[0] int64 i
)
IL_0000: ldc.i4.4
IL_0001: conv.i8
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldsfld int64 ConsoleApplication1.Program::instanceLong
IL_0009: add
IL_000a: ret
} // end of method Program::instanceTest
为什么constTest()有ldc.i4.s?
IL_0004: ldc.i4.s 16
IL_0006: conv.i8
而不是ldc.i8:
IL_0004: ldc.i8 16
因为现在constTest()需要执行conv.i8。
就像我说的,这是纯粹的好奇心。
答案 0 :(得分:3)
这种方式更紧凑,请参阅提示标签。
IL_0000: ldc.i4.4
IL_0001: conv.i8
IL_0002: stloc.0
这需要ldc.i4.4
一个字节和conv.i8
一个字节:总共两个字节。
IL_0004: ldc.i4.s 16
IL_0006: conv.i8
IL_0007: add
ldc.i4.s
和16
需要两个字节,conv.i8
需要一个字节:总共三个字节。
并且ldc.i8 16
将占用指令一个字节,操作数占用4个字节(16):总共5个字节。
但请记住,较短的IL并不意味着一旦它被JIT(或AOT'ed)更快(或更慢)原生。
答案 1 :(得分:1)
请记住,您正在查看IL,而不是最终的机器代码。 IL的目标是尽可能地捕获代码/程序员意图,以便JITTER可以执行最佳的优化。
如果JITTER这样做会引起关注,但编译器执行此操作时无需担心。
答案 2 :(得分:1)
简单的答案是'这是编译器生成代码的方式'。您必须记住,实际生成的本机代码可以在32位或64位CPU上运行。 IL被编译为目标指令集,因此:
ldc.i4 4
conv.i8
很可能成为64位CPU上的单个负载。