开关变量声明的范围如何?
How is switch variable declaration scoped?
跟随怎么可能?
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
不能在不同的 switch case 中声明。它必须在一个块内。
如果没有块,则不可能遵循变量范围。
{
// 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
变量。这个错误是在编译器的语义分析阶段吗?
Question is, how is x scoped inside each case without any visible blocks. meanwhile, variable invalid cant be declared in different switch cases. it has to be inside a block.
在 case 标签中通过模式匹配引入的变量仅具有该 case 主体的范围。
案例主体中引入的变量 "normally" 具有整个 switch 语句的作用域。
是的,它不一致 - 但我认为:
- 能够通过模式匹配引入同名的多个变量特别有用
case
语句中引入的变量作用域从一开始就是一个设计错误,这只是为了防止错误进一步发展
请注意,对于使用相同 case 块的 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;
}
可以说编译器 可以 有一些规则允许您引入多个变量,只要它们属于同一类型 - 这对于通用代码来说可能非常方便。但这肯定会使语言变得更加复杂...
作为 "design mistake" 点的一个例子,C# 5 规范实际上有一个错误。 C# 5 规范 (8.7.2) 声明:
The “no fall through” rule prevents a common class of bugs that occur in C and C++ when break statements are accidentally omitted. In addition, because of this rule, the switch sections of a switch statement can be arbitrarily rearranged without affecting the behavior of the statement.
无论如何,由于模式匹配顺序,此 "arbitrary rearrangement" 在 C# 7 中是不正确的,但它始终是不正确的。考虑这段代码:
class Test
{
static void Main(string[] args)
{
switch (args.Length)
{
case 0:
string x;
break;
case 1:
x = args[0];
break;
}
}
}
这是有效的,因为奇怪的范围规则 - x
在范围内并且可以在 "case 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 块来说更有意义引入一个新的变量声明 space,或者 C# 无论如何都需要 case 块的大括号。
跟随怎么可能?
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
不能在不同的 switch case 中声明。它必须在一个块内。
如果没有块,则不可能遵循变量范围。
{
// 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
变量。这个错误是在编译器的语义分析阶段吗?
Question is, how is x scoped inside each case without any visible blocks. meanwhile, variable invalid cant be declared in different switch cases. it has to be inside a block.
在 case 标签中通过模式匹配引入的变量仅具有该 case 主体的范围。
案例主体中引入的变量 "normally" 具有整个 switch 语句的作用域。
是的,它不一致 - 但我认为:
- 能够通过模式匹配引入同名的多个变量特别有用
case
语句中引入的变量作用域从一开始就是一个设计错误,这只是为了防止错误进一步发展
请注意,对于使用相同 case 块的 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;
}
可以说编译器 可以 有一些规则允许您引入多个变量,只要它们属于同一类型 - 这对于通用代码来说可能非常方便。但这肯定会使语言变得更加复杂...
作为 "design mistake" 点的一个例子,C# 5 规范实际上有一个错误。 C# 5 规范 (8.7.2) 声明:
The “no fall through” rule prevents a common class of bugs that occur in C and C++ when break statements are accidentally omitted. In addition, because of this rule, the switch sections of a switch statement can be arbitrarily rearranged without affecting the behavior of the statement.
无论如何,由于模式匹配顺序,此 "arbitrary rearrangement" 在 C# 7 中是不正确的,但它始终是不正确的。考虑这段代码:
class Test
{
static void Main(string[] args)
{
switch (args.Length)
{
case 0:
string x;
break;
case 1:
x = args[0];
break;
}
}
}
这是有效的,因为奇怪的范围规则 - x
在范围内并且可以在 "case 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 块来说更有意义引入一个新的变量声明 space,或者 C# 无论如何都需要 case 块的大括号。