如何追随?
switch (param.ParameterType)
{
case Type x when x == typeof(byte):
int invalid;
break;
case Type x when x == typeof(short):
int invalid;
break;
case Type x when x == typeof(int):
break;
case Type x when x == typeof(long):
break;
}
问题是,x
如何在每个案例范围内没有任何可见的块。同时,变量invalid
不能在不同的开关情况下声明。它必须在一个街区内。
如果没有阻塞,则无法对变量进行范围界定。
{
// case byte:
Type x;
int invalid;
// break;
// case short:
Type x; // x can not be declared twice.
int invalid;
}
如果每个案例都有不可见的块,则必须遵循以下规则(但不是)。
{
{ // block for each case.
// case byte:
Type x;
int invalid;
// break;
}
{
// case short:
Type x;
int invalid; // but this throws compile time error.
}
}
似乎编译器在这里做了一些魔术,显然x
的范围与invalid
变量不同。这是编译器语义分析阶段的错误吗?
答案 0 :(得分:8)
问题是,如何在每个案例中使用x作用域而没有任何可见的块。同时,变量无效不能在不同的开关情况下声明。它必须在一个街区内。
在案例标签中通过模式匹配引入的变量仅具有该案例的主体范围。
在case主体中“正常”引入的变量具有整个switch语句的范围。
是的,这是不一致的 - 但我认为:
case
语句中引入的变量范围是一个设计错误,这只是为了防止错误进一步发展请注意,对于使用相同大小写块的情况,您不能使用模式匹配多次声明同一变量。例如,通过简化代码,这很好:
object o = null;
switch (o)
{
case Type x when x == typeof(byte):
break;
case Type x when x == typeof(short):
break;
}
但这不是:
object o = null;
switch (o)
{
case Type x when x == typeof(byte):
case Type x when x == typeof(short):
break;
}
可以说编译器可以有一些规则允许你引入多个变量,只要它们属于同一类型 - 这对于公共代码来说非常方便。但它肯定会使语言变得更加复杂......
作为“设计错误”点的一个例子,C#5规范实际上由于它而产生错误。 C#5规范(8.7.2)声称:
“不通过”规则可以防止在意外省略break语句时C和C ++中出现的常见错误类。另外,由于这个规则,switch语句的switch部分可以任意重新排列,而不会影响语句的行为。
由于模式匹配排序,这种“任意重新排列”在C#7中是不真实的,但它始终是不真实的。请考虑以下代码:
class Test
{
static void Main(string[] args)
{
switch (args.Length)
{
case 0:
string x;
break;
case 1:
x = args[0];
break;
}
}
}
由于奇怪的范围规则,这是有效的 - x
在范围内,可用于“案例1”块。但是,如果您重新安排案例:
class Test
{
static void Main(string[] args)
{
switch (args.Length)
{
case 1:
x = args[0]; // Invalid
break;
case 0:
string x;
break;
}
}
}
...现在这会产生编译时错误。变量仍然在范围内(编译器知道x
的含义)但是在声明之前你不能为局部变量赋值。
据我所知,没有人希望使用早期作用域声明的变量 - 对于每个case块引入新的变量声明会更有意义空间,或C#要求案件块的大括号。