Switch statements in CSharp
For those using a RSS reader, subscribe here: rss.xml
Note: if you decide to implement what is discussed in this blog post, refer to this blog post.
Look carefully at this snippet of code:
switch(mode) { case Mode.ELITEmode: if (someCondition) return false; case Mode.NORMALmode: break; default: throw new ArgumentOutOfRangeException(); }
Do you see anything odd? This is not valid C# code sadly, here is the version that is valid:
switch(mode) { case Mode.ELITEmode: if (someCondition) return false; goto normal; case Mode.NORMALmode: normal: break; default: throw new ArgumentOutOfRangeException(); }
Eew goto-statement!
Generating proper fall-through switch statements with this hack
So do you want to make a language feature in C#? Implement this one, doesn’t even take much thought: slap unique label between around case lines like this for every case. Pre-process it as follows:
Before
switch(mode) { case Mode.NORMIEmode: case Mode.ELITEmode: if (someCondition) return false; case Mode.NORMALmode: break; case Mode.NORMALmode: break; default: throw new ArgumentOutOfRangeException(); }
After; label version
switch(mode) { case Mode.NORMIEmode: UNIQUE_CASE_1: // Note that empty body case already has this fall-through // Just not executed code in-between goto UNIQUE_CASE_2; case Mode.ELITEmode: UNIQUE_CASE_2: if (someCondition) return false; goto UNIQUE_CASE_3; case Mode.NORMALmode: UNIQUE_CASE_3: break; // or continue; or return; // Still generate, not called anyway // Look into optimizing later ;D goto UNIQUE_CASE_4; case Mode.IMPOSSIBLEmode: UNIQUE_CASE_4: break; default: throw new ArgumentOutOfRangeException(); }
After; repeat expression version
switch(mode) { case Mode.NORMIEmode: // Note that empty body case already has this fall-through // Just not executed code in-between goto case Mode.ELITEmode; case Mode.ELITEmode: if (someCondition) return false; goto case Mode.NORMALmode; case Mode.NORMALmode: break; // or continue; or return; // Still generate, not called anyway // Look into optimizing later ;D goto case Mode.IMPOSSIBLEmode; case Mode.IMPOSSIBLEmode: break; default: throw new ArgumentOutOfRangeException(); }
Comparing to other analysis
On a StackOverflow discussion, it pointed out the language feature where you repeat the matched expression after the `goto` keyword; But I will argue the label method is nicer, as it allows a consistent output of the pre-processor, instead of copying whatever expression is cased against. Whatever you may prefer for your preprocessor to output, in both cases you introduce something to go to the next case.