我正在研究从这个C#代码(Release)生成的IL代码:
int a = Convert.ToInt32(Console.ReadLine());
switch(a)
{
case 1: Console.WriteLine(); break;
case 2: Console.WriteLine(); break;
case 3: Console.WriteLine(); break;
case 15: Console.WriteLine(); break;
default: Console.WriteLine(); break;
}伊:
//Why not "switch(IL_0026, IL_002c, IL_0032, IL_0038)"?
IL_000e: switch (IL_0026, IL_002c, IL_0032)
IL_001f: ldloc.0
IL_0020: ldc.i4.s 15
IL_0022: beq.s IL_0038
IL_0024: br.s IL_003e
IL_0026: call void [System.Console]System.Console::WriteLine()
IL_002b: ret
IL_002c: call void [System.Console]System.Console::WriteLine()
IL_0031: ret
IL_0032: call void [System.Console]System.Console::WriteLine()
IL_0037: ret
IL_0038: call void [System.Console]System.Console::WriteLine()
IL_003d: ret
IL_003e: call void [System.Console]System.Console::WriteLine()
IL_0043: ret为什么IL中的“开关”与序列(1,2,3.n+1)和不添加其他值(对于exapmle:对于生成的15条指令(001f,0020,0022))
发布于 2022-01-19 10:34:06
//为什么不“交换(IL_0026,IL_002c,IL_0032,IL_0038)"?
因为如果a的值是4,而不是15,那么第4个标签就会被跳到。switch中的跳转目标对应于测试值的连续值。
为了使用switch而没有15的额外特例,需要:
switch(IL_0026, IL_002c, IL_0032, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_003e, IL_0038)(我希望我数对了)
这将是一个更大的跳台。
我总是建议查看您正在查看的指令的Reflection.Emit文档,例如OpCodes.Switch,以确保您理解该指令的功能。
开关指令从堆栈中弹出一个值,并将其作为无符号整数与
N进行比较。如果值小于N,则执行转移到按值索引的目标,其中目标编号从0(例如,值0接受第一个目标,值1接受第二个目标,等等)。
https://stackoverflow.com/questions/70768899
复制相似问题