为什么在一个case语句中声明的变量在其他情况下的范围内?

时间:2012-09-13 23:34:44

标签: c# compiler-construction switch-statement

为什么以下代码会编译?我希望它会抱怨foo没有在第二个案例分支中被宣布。编译器是否处理声明,使其适用于所有情况?

using System;

namespace Scratch
{
    class Scratch
    {
        public static void Main()
        {
            var x = 2;
            switch (x)
            {
                case 1:
                    var foo = "one";
                    Console.Out.WriteLine(foo);
                    break;
                case 2:
                    foo = "two"; // is foo in scope here?
                    Console.Out.WriteLine(foo);
                    break;
            }
        }
    }
}

4 个答案:

答案 0 :(得分:8)

  

为什么以下代码会编译?

因为语言是在这个特定领域以脑死亡的方式设计的:(

局部变量的范围是声明它的,并且在声明后可以在任何一点上以词汇方式访问。

不,我也不会那样设计语言。我不喜欢C#中的开关设计......

答案 1 :(得分:8)

@JonSkeet所说的是正确的:C / C ++ / C#意义上的“块”与逻辑意义上的“案例”不同。但他没有提到修复问题的“最佳实践”:如果要在switch语句的一个case中声明一个变量,最好将整个逻辑“case”包装在一个块中。这样,编译器识别的逻辑“案例”和实际“范围”将是同一个。

public static void Main()
{
    var x = 2;
    switch (x)
    {
        case 1: {  // notice these braces I added
            var foo = "one";
            Console.Out.WriteLine(foo);
            break;
        }
        case 2:
            foo = "two"; // hooray! foo is no longer in scope here
            Console.Out.WriteLine(foo);
            break;
    }
}

答案 2 :(得分:3)

为了使它不能编译,你可以用这样的大括号范围:

using System;

namespace Scratch
{
    class Scratch
    {
        public static void Main()
    {
        var x = 2;
        switch (x)
        {
            case 1:
            {
                var foo = "one";
                Console.Out.WriteLine(foo);
                break;
            }
            case 2:
            {
                foo = "two"; // is foo in scope here?
                Console.Out.WriteLine(foo);
                break;
            }
        }
    }
}

这会强制var foo仅存在于该特定范围内。

答案 3 :(得分:1)

在C#中,变量的作用域是块级。由于块跟在switch语句之后,foo确实在两种情况下都在范围内。