6

为什么下面的代码会编译?我希望它会抱怨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

4 回答 4

9

为什么下面的代码会编译?

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

局部变量的范围是声明它的块,并且在声明之后的任何时候都可以在词法上访问它。

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

于 2012-09-13T23:36:56.487 回答
8

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

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;
    }
}
于 2012-09-13T23:43:43.447 回答
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 仅存在于该特定范围内。

于 2012-09-13T23:42:05.763 回答
1

在 C# 中,变量的作用域是块级别。由于该块遵循 switch 语句,因此 foo 在这两种情况下都确实在范围内。

于 2012-09-13T23:39:56.913 回答