切换语句的奇怪行为

  • 本文关键字:语句 c# enums
  • 更新时间 :
  • 英文 :


可能重复:
c#开关语句中的变量声明
Switch案例中额外支架的用途是什么?

今天我在写一小段代码,在调试时,VS打了我一巴掌,告诉我我的局部变量名称犯了一个大错误:"一个名为‘I’的局部变量已经在这个范围中定义了"。

MyEnum enumerator = MyEnum.B;
switch (enumerator)
{
    case MyEnum.A:
        Int32 i = 0;
        // DoStuffsA();
        break;
    case MyEnum.B:
        Double i = 0D;
        // DoStuffsB();
        break;
}

所以我说:"好吧,VS,让我稍后解决它,我想先确定我的案例范围,因为我更喜欢它们!"。所以我做了整容手术。。。但突然VS停止抱怨这个错误:

MyEnum enumerator = MyEnum.B;
switch (enumerator)
{
    case MyEnum.A:
    {
        Int32 i = 0;
        // DoStuffsA();
        break;
    }
    case MyEnum.B:
    {
        Double i = 0D;
        // DoStuffsB();
        break;
    }
}

好的。。。我知道"scope"的含义,我知道我产生了两个不同的scope。问题是我不知道switch语句是如何翻译成IL代码的,我一直认为无论是否使用大括号,所有的case语句都被放在switch作用域中。所以…下面的怪事是可以编译的,对吧?

MyEnum enumerator = MyEnum.B;
switch (enumerator)
{
    case MyEnum.A:
        String s = "Hello!";
        Console.WriteLine(s);
        break;
    case MyEnum.B:
        s = "Goodbye!";
        Console.WriteLine(s);
        break;
}

但不是以下一个:

MyEnum enumerator = MyEnum.B;
switch (enumerator)
{
    case MyEnum.A:
    {
        String s = "hello";
        Console.WriteLine(s);
        break;
    }
    case MyEnum.B:
    {
        s = "goodbye";
        Console.WriteLine(s);
        break;
    }
}

有人能更好地解释编译器在这种情况下的行为吗?非常感谢!

在不同的case块中添加{}时,将引入作用域

没有它们,所有case块都在一个范围内。

在最后两个例子中,使用s-第一个很好,因为s是在case中为MyEnum.A声明的,所以可以在MyEnum.B中使用,但使用大括号时,MyEnum.A中的声明在其自己的范围内,在外部不可见-所以在MyEnum.B中,s是未知的,需要重新声明。

首先,到IL的翻译有些无关紧要。IL根本没有相同的范围概念。这一切都与C#语言规范有关。

实际上,这很简单:局部变量的作用域是声明它的,当另一个同名局部变量在作用域中时,不能声明一个局部变量。

  • 在您的第一段代码中,i的作用域是整个switch语句。您的第二个声明试图在同一范围内声明另一个i变量,因此它失败了。

  • 在第二段代码中,每个i变量的作用域只是由大括号创建的块——它们处于完全独立的作用域中,没有嵌套,所以没关系。

  • 在您的第三段代码中,变量s在第二种情况的作用域中,因为它的作用域是整个switch语句,所以可以使用它

  • 在您的第四段代码中,变量s在声明它的块的作用域中仅(在情况A中(,因此在情况B中不在作用域中。

我强烈建议不要使用像第三段代码那样的代码。这会使许多人感到困惑。如果你真的想要一个在多个情况下都有效的变量,我会在switch语句之前声明它

break放在大括号内会导致它断裂到大括号的末端,此时case会穿过。您需要大括号之外的break语句。例如

case MyEnum.A:
{
    String s = "hello";
    Console.WriteLine(s);
}
break;

相关内容

  • 没有找到相关文章

最新更新