C# Switch Statement: More efficient to not use default?
我在Visual Studio中创建了一个C方法,该方法只包含一个switch语句,其中每个case都返回一个值。根据个人习惯,我将类似于以下代码的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 | private string SwitchMethod(int num) { switch (num) { case 0: return"result 1"; case 1: return"result 2"; case 2: return"result 3"; } return"no result"; } |
我的问题是:哪个代码的性能更好?上面或下面的代码,还是相同的?为什么?
我假设由于编译器的优化…它们可能是相同的…但我真的不知道。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | private string SwitchMethod(int num) { switch (num) { case 0: return"result 1"; case 1: return"result 2"; case 2: return"result 3"; default: return"no result"; } } |
修订:似乎我应该更具体一点:编译时,效率较低的代码是由一个还是另一个生成的?
我意识到表演上的差异可能是微不足道的…我只是好奇而已。
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static string foo(int num) { switch (num) { case 0: return"result 1"; case 1: return"result 2"; case 2: return"result 3"; } return"no result"; } |
变成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | .method public hidebysig static string foo(int32 num) cil managed { // Code size 57 (0x39) .maxstack 1 .locals init ([0] string CS$1$0000, [1] int32 CS$4$0001) IL_0000: nop IL_0001: ldarg.0 IL_0002: stloc.1 IL_0003: ldloc.1 IL_0004: switch ( IL_0017, IL_001f, IL_0027) IL_0015: br.s IL_002f IL_0017: ldstr "result 1" IL_001c: stloc.0 IL_001d: br.s IL_0037 IL_001f: ldstr "result 2" IL_0024: stloc.0 IL_0025: br.s IL_0037 IL_0027: ldstr "result 3" IL_002c: stloc.0 IL_002d: br.s IL_0037 IL_002f: ldstr "no result" IL_0034: stloc.0 IL_0035: br.s IL_0037 IL_0037: ldloc.0 IL_0038: ret } // end of method Program::foo |
将返回移动到默认情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | .method public hidebysig static string foo(int32 num) cil managed { // Code size 57 (0x39) .maxstack 1 .locals init ([0] string CS$1$0000, [1] int32 CS$4$0001) IL_0000: nop IL_0001: ldarg.0 IL_0002: stloc.1 IL_0003: ldloc.1 IL_0004: switch ( IL_0017, IL_001f, IL_0027) IL_0015: br.s IL_002f IL_0017: ldstr "result 1" IL_001c: stloc.0 IL_001d: br.s IL_0037 IL_001f: ldstr "result 2" IL_0024: stloc.0 IL_0025: br.s IL_0037 IL_0027: ldstr "result 3" IL_002c: stloc.0 IL_002d: br.s IL_0037 IL_002f: ldstr "result 4" IL_0034: stloc.0 IL_0035: br.s IL_0037 IL_0037: ldloc.0 IL_0038: ret } // end of method Program::foo |
完全一样。没有性能差异。我将"无结果"更改为结果4,只是为了确保代码重新生成。显然,C编译器优化了它,或者它最终是等价的。
对于其他情况都无效的情况,最好在开关的基础上始终包含默认情况。
这不是一个效率问题,因为如果点击了前面的一个案例-您的程序将不会检查任何其他案例(它相当于使用if/else if/else-其中final else是默认的)。
希望这有帮助。
与其使用函数和switch语句,不如使用通用字典,其中键为kofaxenvironment,值与从开关返回的值相同。类似:
1 | Dictionary<KofaxEnvironment, string> |
或
1 | Dictionary<int, string> |
我也不会担心性能。正确性应该是您的第一个目标。
但是,如果您坚持使用开关,请使用引发异常的默认值:
1 2 |
至于性能,交换机默认值和返回值之间的差异(如果有)可以忽略不计。