The question is, how is x in each case without visible blocks. Meanwhile, an invalid variable cannot be declared in different switching cases. It must be inside the block.
Variables entered using pattern matching if labels have only the body area of this case.
Variables entered "usually" in body bodies have the scope of the entire switch statement.
Yes, this is contradictory - but I would say that:
- It is especially useful to be able to enter several variables with the same name using pattern matching
- The scope of the variables introduced in the
case expressions was a design error, and this simply prevents further error.
Note that you cannot declare the same variable multiple times using pattern matches for cases that use the same case block. For example, simplifying your code is fine:
object o = null; switch (o) { case Type x when x == typeof(byte): break; case Type x when x == typeof(short): break; }
But this is not so:
object o = null; switch (o) { case Type x when x == typeof(byte): case Type x when x == typeof(short): break; }
Perhaps the compiler may have some rules that allow you to enter several variables, if they are of the same type - this can be very convenient for general code. But it will definitely make the language even more complex ...
As an example of a design error point, the C # 5 specification really has an error because of it. The C # 5 specification (8.7.2) states:
The "no-skip" rule prevents a common class of errors that occur in C and C ++ when break statements are accidentally excluded. In addition, because of this rule, the switch sections of the operator statement can be arbitrarily rearranged without affecting the behavior of the operator.
This “arbitrary rearrangement” is in any case incorrect in C # 7 due to the pattern matching order, but has always been incorrect. Consider this code:
class Test { static void Main(string[] args) { switch (args.Length) { case 0: string x; break; case 1: x = args[0]; break; } } }
This is acceptable due to the odd rules for determining the scope - x is in scope and can be used in the "case 1" block. However, if you change the order of things:
class Test { static void Main(string[] args) { switch (args.Length) { case 1: x = args[0];
... now this gives a compile-time error. The variable is still in scope (the compiler knows what you mean by x ), but you cannot assign a value to a local variable before declaring it.
As far as I know, no one will ever want to use a variable declared in an earlier scope - it would be more reasonable to introduce a new variable declaration space for each block of the case, or for C #, requiring brackets for the block of the case anyway.