gpt4 book ai didi

c# - 开关变量声明的范围如何?

转载 作者:太空狗 更新时间:2023-10-29 22:35:50 27 4
gpt4 key购买 nike

跟随怎么可能?

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;
}

问题是,在没有任何可见 block 的情况下,x 是如何限定在每个 case 中的?同时,变量 invalid 不能在不同的 switch case 中声明。它必须在一个 block 内。

如果没有 block ,那么遵循变量的作用域是不可能的。

{
// case byte:
Type x;
int invalid;
// break;

// case short:
Type x; // x can not be declared twice.
int invalid;
}

如果每种情况都有不可见 block ,则必须可以进行以下操作(但不是)。

{
{ // 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 主体的范围。

在 case 主体中“正常”引入的变量具有整个 switch 语句的范围。

是的,这是不一致的 - 但我认为:

  • 能够通过模式匹配引入同名的多个变量特别有用
  • case 语句中引入的变量范围从一开始就是一个设计错误,这只是为了防止错误进一步发展

请注意,对于使用相同 case block 的 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) 声明:

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.

无论如何,由于模式匹配顺序,这种“任意重新排列”在 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” block 中使用。但是,如果您重新排列大小写:

class Test
{
static void Main(string[] args)
{
switch (args.Length)
{
case 1:
x = args[0]; // Invalid
break;
case 0:
string x;
break;
}
}
}

... 这现在给出了一个编译时错误。该变量仍在范围内(编译器知道您所说的 x 是什么意思),但您不能在局部变量声明之前为其赋值。

据我所知,没有人想要使用由早期作用域声明的变量——如果每个 case block 都引入一个新的变量声明会更有意义空格,或者 C# 无论如何都需要 case block 的大括号。

关于c# - 开关变量声明的范围如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46877386/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com