如何阻止C#';s switch语句,以生成CIL switch指令
C#的switch语句可以编译成CIL switch指令,或者if/else,具体取决于前面提到的语句中的情况。有没有办法强制编译器在代码块中始终生成if/else变量?最简单的方法是在代码中使用if/else。除此之外,这让读者更清楚地知道,这就是你想要发生的事情,而不是使用开关如何阻止C#';s switch语句,以生成CIL switch指令,c#,clr,switch-statement,C#,Clr,Switch Statement,C#的switch语句可以编译成CIL switch指令,或者if/else,具体取决于前面提到的语句中的情况。有没有办法强制编译器在代码块中始终生成if/else变量?最简单的方法是在代码中使用if/else。除此之外,这让读者更清楚地知道,这就是你想要发生的事情,而不是使用开关 编辑:好的,所以可读性对你来说并不重要——但基本上如果你想修改编译后的代码,源代码就必须修改。您可以使用Mono编译器并自己修改它,但我怀疑是否有任何方法可以让Microsoft编译器有效地忽略您使用的是switch
编辑:好的,所以可读性对你来说并不重要——但基本上如果你想修改编译后的代码,源代码就必须修改。您可以使用Mono编译器并自己修改它,但我怀疑是否有任何方法可以让Microsoft编译器有效地忽略您使用的是switch语句。您是否尝试过其他编译器(即Mono),或者试图将有问题的类放在一个单独的程序集中并切换到另一种语言?您是如何让编译器做到这一点的? 我用VS2008做了一个测试:
public static int DoSomething(int i) {
switch (i) {
case 1: return 0;
case 100: return 1;
case 1000: return 2;
default: return 3;
}
}
汇编至:
.method public hidebysig static int32 DoSomething(int32 i) cil managed
{
.maxstack 2
.locals init (
[0] int32 CS$1$0000,
[1] int32 CS$4$0001)
L_0000: nop
L_0001: ldarg.0
L_0002: stloc.1
L_0003: ldloc.1
L_0004: ldc.i4.1
L_0005: beq.s L_0016
L_0007: ldloc.1
L_0008: ldc.i4.s 100
L_000a: beq.s L_001a
L_000c: ldloc.1
L_000d: ldc.i4 0x3e8
L_0012: beq.s L_001e
L_0014: br.s L_0022
L_0016: ldc.i4.0
L_0017: stloc.0
L_0018: br.s L_0026
L_001a: ldc.i4.1
L_001b: stloc.0
L_001c: br.s L_0026
L_001e: ldc.i4.2
L_001f: stloc.0
L_0020: br.s L_0026
L_0022: ldc.i4.3
L_0023: stloc.0
L_0024: br.s L_0026
L_0026: ldloc.0
L_0027: ret
}
那里没有开关指令
也许您应该向Microsoft提交一个bug?不,您无法控制C#编译器如何发出CIL指令。即使可以,AOT或JIT编译器也可能会将CIL指令转换为本机机器码指令,这与由于高级编译器优化而产生的预期截然不同。为什么要这样做?switch语句是由词法分析器生成的,因此可读性不成问题。重写生成器以生成if/else是最后的选择:)我没有可用的编译器ATM,但是如果为值为1-1000(因此有1000个条目)的3格开关创建跳转表,我会感到震惊。可能更接近案例1:案例50:我也会,但如果编译器没有在您的案例中选择最佳代码,我会感到惊讶。请注意,仅我的三个案例就导致了20条IL指令被发出。编译器确实为执行速度选择了最佳代码,我想优化内存使用。20条IL指令占用的内存仍然比50-100条跳转表少得多。JIT编译器做什么?优化MSIL/CIL只是为了让JIT编译器悲观化它是没有意义的。C#switch语句只在值相邻时生成IL开关指令(给或取几个孔)。如果它们不是,它将与bgt(条件跳转)一起使用。对于开关,VB的Select的工作方式相同,但如果值不相邻,则将使用常规if。