@bfEAsefEEAECBteXW~| 475454VC 7888}555WC G7845VYBZZZBC-~~ 47VBCC 5557464G74V~ G75V G755V G75VCC 77F8WC 954754754G5556VCC 95475474V~B~B~BZC-~X

Switch.` You find yourself in a mysterious dungeon. There is a dim light from above. The cell door is locked. You notice a box full of 1000 keys, all different.`After trying 5 keys,` you realize a faster way to switch keys is needed. As a developer, you know a switch statement has lookup table optimizations. Switch is your only hope now.`First example.` This program uses a switch. It introduces an int local. With a switch, it tests the int against two constants—1 and 5. Doom is no longer certain. `Caution: `Not every variable can be used in a switch. Most built-in value types, like int or char, work.`Strings: `A switch can handle strings. These are implemented in a different way. They use a hidden Dictionary.`Another example.` This includes curly brackets and the default case. The program accepts an int from the user (with ReadLine). It then tests it for six values. `We see how the curly brackets are used in the switch cases. And we combine some of the case statements.`Strings.` Often we switch on values, like numbers. The contents of strings are not value types—they are collections of characters. But with special support, we switch on strings too. `The C# compiler detects a string switch and can optimize it with a Dictionary lookup.`Note 2: `Small string switches, like this one with just 3 cases, are often not compiled into Dictionaries. Performance is better this way.`Types.` It is possible to switch on integers or other value types, such as enums or chars. Strings are a reference type, but the C# compiler can handle switches on strings as well. `Switch Char `switch-char`Switch Enum `switch-enum`Switch String `string-switch`Case.` We use this keyword to specify a matching constant. Some cases (default) do not use the case keyword. We end a case with "break" or "return." `Case `case`Goto.` We can use goto statements in switches. These are different from other gotos. With goto we can run multiple cases for a single expression. `Goto, Switch `goto`Break.` This keyword is used within switches. And continue may also be used. These 2 keywords are used also within loops. Sometimes they are used in both loop and switch statements. `Break `break`Continue `continue`So: `Are you breaking out of a switch, or out of the enclosing loop? Scope is important: the deepest construct is broken first.`Double.` Some values may not be switched upon. Floating-point values, like doubles, will cause an error in a switch expression. Most classes and custom types will also fail. `Bool: `A bool may be used in the expression of a switch. But this is somewhat strange as only true and false are allowed.`Nullable: `A nullable type can be used, but only if the nullable type "wraps" a valid switch type like an enum.`Nested switch.` Sometimes one switch is not enough. But we can nest a switch within another switch, successively testing values. This approach is sometimes helpful. `Nested Switch `nested-switch`But: `Our code logic, with nested switches, quickly turns into a mess. With comments, this approach may succeed.`I test the first two elements in an int array with switches. The second element is tested if the first is 4.`Fall through.` Every case must have a break, continue, goto, return or throw at its end. In C# we cannot have cases with statements fall through to the following case. `Goto: `We can use the goto statement, as in "goto case 1," to run both cases on a 0 value. As shown, the program does not compile.`Duplicate cases.` A switch can only have unique case labels—each constant value must be distinct. This program will not compile. But it shows us what happens when we have duplicate cases. `Constants.` We must use only constants for case statements. This is a limitation, but it is part of the language specification. The C# compiler is not even tempted. `Benchmark.` A switch statement helps optimize some programs. Suppose a method that must return a value based on a small range of inputs. We can use switch to test these values. `Method 1 uses a switch statement. But method 2 instead uses a series of if-statements.`The benchmark shows that the switch statement version is slightly faster. Those nanoseconds may come in handy someday.`Pattern matching, types.` We can use pattern matching on types in a switch. We switch on a variable. In each case, we can match its type. A local variable (cast to that type) can be used. `We introduce a class hierarchy—the Bird and Cat classes inherit from Animal. We then create some class instances.`We match the types of the Animal class. The most derived class is matched first—in this switch form, order matters.`Pattern matching, when.` We can place a condition on each case statement. This can test another variable. Here we test a local variable called secondValue on the first 2 cases. `We have repeat "case 200" statements. They are different only because of their "when" clauses.`Tip 2: `With the "when pattern-matching" syntax, order matters in a switch. This is an enhanced syntax form.`Speed.` Switch can be implemented with a jump table in the intermediate language. Large switches can be much faster than long series of if-else statements. `1. If and switch. `The if-statement sometimes performs better than the switch. Testing is essential.`If, Switch Comparison `if-switch-performance`2. Regex and switch. `The switch statement can be used to replace a Regex method call. This can make programs much faster.`Regex, Switch `regex-versus-loop`3. Intermediate language: `Switch is often implemented at a lower level with the switch opcode. We show an example.`IL: switch `il`Usage.` Should we use switches everywhere? This is probably a bad idea. With polymorphism, we abstract selections with virtual methods and inheritance. This leads to cleaner code. `Virtual `virtual`So: `If you want to use switches everywhere in your code, go ahead. But don't expect to be admired for it.`Refactoring.` We consider a quote from the book Refactoring, which teaches us how to improve code so the code is not terrible. Well-designed code is easier to maintain. `Quote: `The problem with switch statements is essentially that of duplication. Often you find the same switch statement scattered around a program in different places. If you add a new clause to the switch, you have to find all these switch statements and change them (Refactoring).`Some thoughts.` Switches often outperform if-statements. But more importantly, they help with code design. They enforce all values tested are constants.`Symmetry.` This construct imparts a greater sense of symmetry. Switches test value types and strings. They speed up selections. And with them, we write clearer code.

?@F @P@O@S@D@; { ?@$?{ ??@s@d@zF5F; ??F@NF (@d) ??{@'FcaseF F1F:@'?@%1);@'?@C@'FcaseF F5F:@'?@%5);@'?@C ??} ?} } F 5F @D@; { ?@$?{ ??@g (true) ??{@'@O.@%"Type @G@Rpress Return");@'try@'{@'?@si@z@}.Parse(@O.@4.@xLine());@'?F@NF (i)@'?{@'??@VF0F:@'??@VF1F:@'??@VF2F:@'???{@'????@O.@%"Low @G");@'????@C@'???}@'??@VF3F:@'??@VF4F:@'??@VF5F:@'???{@'????@O.@%"Medium @G");@'????@C@'???}@'??default:@'???{@'????@O.@%"Other @G");@'????@C@'???}@'?}@'}@'catch@'{@'} ??} ?} } F Type @G@Rpress Return F5F Medium @G Type @G@Rpress Return F2F Low @G Type @G@Rpress Return F500F Other @GF @P@O@S@D@; { ?@$?{ ??@L @d@z"turnip";F ??@2Switch on the @L. ??F@NF (@d) ??{@'@VF"lettuce"F:@'?@%"LETTUCE");@'?@C@'@VF"squash"F:@'?@%"SQUASH");@'?@C@'@VF"turnip"F:@'?@%F"TURNIP"F);@'?@C ??} ?} } F TURNIPF @D@; { ?@$?{ ??double @d@zF1.4F; ??F@NF (@d) ??{@'@V1:@'?@C ??} ?} } F Error 1 A @N expression or @Vlabel must be a bool, char, @L, @}egral, enum, or corresponding nullable type....F @P@O@S@D@; { ?@$?{ ??@}[] @T@z{ F4F, F10F, F14F }; ??F@NF (@T[0]) ??{@'@VF3F:@'?@%3);F @{Not reached.@'?F@C @'@VF4F:@'?@%4);F@'?@2Use nested @N.@'?F@NF (@T[1])@'?{@'??@VF10F:@'???@%10);@'???@C@'?}@'?@C ??} ?} } F 4 10F @P@O@S@D@; { ?@$?{ ??@s@d@z0;F ??@2Every @N statement must be terminated. ??F@NF (@d) ??{@'F@V0F:@'?@%"Zero");@'@V1:@'?@%"One");@'?@C ??} ?} } F Error 1 Control cannot fall through from one @Vlabel ('@V0:')@lanotherF @P@O@S@D@; { ?@$?{ ??short @G@z0;F ??@2Cases may not be duplicated. ??F@NF (@G) ??{@'F@V0:F@'F@V0:F@'?@%"ZERO");@'?@J;@'@V1:@'?@%"ONE");@'?@J; ??} ?} } F Error 1 The label '@V0:' already occurs@kthis @N statementF @P@O@S@D@; { ?@$?{ ??@s@G@z0; ??@stest@z10;F ??@2Constant @ds are required. ??F@NF (@G) ??{@'F@Vtest@y1:F@'?@%100);@'?@J;@'@V0:@'?@%0);@'?@J; ??} ?} } F Error 1 A constant @d is expectedF @P@O; @! @D@; { ?@A@sM@[1(@sv) ?{ ??F@NF (v) ??{@'@V0:@'?@J 10;@'@V1:@'?@J -1;@'@V2:@'?@J 20;@'default:@'?@J 0; ??} ?} ?@A@sM@[2(@sv) ?{ ??FifF (v@i0) @J 10; ??@rv@i1) @J -1; ??@rv@i2) @J 20; ??@J 0; ?} ?@$?{ ??M@[1(0); M@[2(0); ??const @smax@z100000000@S??var s1@z@-.@cNew(); ??@o(@si@z0; i < max; i++) ??{@'M@[1(0);@'M@[1(1);@'M@[1(2);@'M@[1(3); ??} ??s1@1; ??var s2@z@-.@cNew(); ??@o(@si@z0; i < max; i++) ??{@'M@[2(0);@'M@[2(1);@'M@[2(2);@'M@[2(3); ??} ??s2@1; ??@%(@.(s1.@" * 1000000) /@'max).To@M("0.00 ns")); ??@%(@.(s2.@" * 1000000) /@'max).To@M("0.00 ns")); ??@4.@x(); ?} } FResultsF F9.25 nsF?[@N] F9.85 nsF?[if]F @P@O@S@DAnimal { ?@=@ssize; } @DBird : Animal { ?@=@scolor; } @DCat : Animal { ?@=bool wild; } @D@; { ?@A@fTest(Animal animal) ?{F ??@{Switch on a @Dtype with pattern matching. ??F@N (animal) ??{@'FcaseF FCat cF:@'?@%F$"CAT wild@z{c.wild}"F);@'?@C@'FcaseF FBird bF:@'?@%F$"BIRD color@z{b.color}"F);@'?@C@'FcaseF FAnimal aF:@'?@%F$"ANIMAL size@z{a.size}"F);@'?@C ??} ?} ?@$?{F ??@{C@` some @Dinstances. ??FCatF cat@z@wCat(); ??cat.wild@ztrue; ??FBirdF bird@z@wBird(); ??bird.color@z5; ??FAnimalF animal@z@wAnimal(); ??animal.size@z10;F ??@{Test @Dinstances. ??FTest(cat); ??Test(bird); ??Test(animal); ?} } F CAT wild@zTrue BIRD color@z5 ANIMAL size@z10F @P@O@S@D@; { ?@$?{ ??@s@d@z200; ??@ssecond@e@z300;F ??@{Use @N with pattern matching. ??F@N (@d) ??{@'FcaseF 200 Fwhen second@e@i0F:@'?@%F"Y"F);@'?@C@'FcaseF 200 Fwhen second@e@i300F:@'?@%F"@e is 200, second@e is 300"F);@'?@C@'FcaseF 400:@'?@%F"Z"F);@'?@C ??} ?} } F @e is 200, second@e is 300F

VswitchZint switch2switches on string:causes switch double error]nested switch6has fall-through error2has duplicate case3lacks constant case1benchmarks switcheswitch, matches typesnpattern matching, when keyword