C#switch语句中的变量声明

Variable declaration in a C# switch statement

为什么在C switch语句中,对于多个情况下使用的变量,只在第一个情况下声明它?

例如,以下引发错误"名为"variable"的局部变量已在此范围内定义"。

1
2
3
4
5
6
7
8
9
switch (Type)
{
    case Type.A:
            string variable ="x";
                break;
    case Type.B:
            string variable ="y";
                break;
}

但是,根据逻辑,如果类型是Type.B,则不应点击初始声明。switch语句中的所有变量是否都存在于单个作用域中,并且在处理任何逻辑之前是否创建/分配了这些变量?


如果希望变量的作用域是特定的大小写,只需将大小写包含在自己的块中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
switch (Type)
{
    case Type.A:
    {
        string variable ="x";
        /* Do other stuff with variable */
    }
    break;

    case Type.B:
    {
        string variable ="y";
        /* Do other stuff with variable */
    }
    break;
}


我认为这与变量的整体范围有关,它是在开关级别定义的块级范围。

就个人而言,如果您在示例中将某个值设置为某个开关内的某个值,以便它真正具有任何益处,那么您无论如何都希望在该开关外声明它。


是的,作用域是整个开关块——不幸的是,IMO。但是,您可以在单个案例中添加大括号,以创建较小的作用域。至于它们是否被创建/分配,堆栈框架有足够的空间来容纳一个方法中的所有局部变量(不考虑捕获变量的复杂性)。这不像是在方法执行期间分配的空间。


因为它们的作用域在开关块上。C语言规范规定如下:

The scope of a local variable or constant declared in a switch block is the switch block.


变量在C编译器中共享作用域。然而,范围在CIL中并不以相同的方式存在。至于实际创建/初始化….NET内存模型允许编译器在遵循简单规则的情况下稍微移动读/写,除非变量被标记为volatile。


"在我的天啊…"

swicth是一个非常原始的程序实现,它在C本身的时代(甚至在C++之前)就已经存在了。

整个switch是一个块,用作包含GOTO:的作用域(因此每个case中的:)。如果你上了一些汇编类,那可能看起来很熟悉。

这就是为什么当与Enums结合时,switch的使用是最有用的,而不是在每一个类似casebreak中使用。

1
2
3
4
5
6
7
8
9
10
11
12
switch(mood)
{
    case Mood.BORED:
    case Mood.HAPPY:
        drink(oBeer) // will drink if bored OR happy
break;

    case Mood.SAD: // unnecessary but proofs a concept
    default:
        drink(oCoffee)
break;
}


初始化发生在这种情况下,但是声明是在作用域的顶部有效地完成的。(伪代码)

1
2
3
4
5
6
7
8
9
10
11
switch (Type)
{
string variable;

    case Type.A:
            variable ="x";
                break;
    case Type.B:
            variable ="y";
                break;
}