为什么我不能在C#的不同范围内声明一个具有相同名称的变量?

Why can't I declare a variable with the same name in different scopes in C#?

本问题已经有最佳答案,请猛点这里访问。

不确定这是否是因为C编译器特别挑剔,但我尝试在C中这样做:

1
2
3
4
5
6
7
8
9
10
11
12
public static void Main()
{
    bool result = true; // some dummy value
    if(result)
    {
        int x = 5;
        Console.WriteLine(x);
    }

    int x = 10;
    Console.WriteLine(x);
}

编译器抱怨变量名"x"已经被使用:

A local variable named 'x' cannot be declared in this scope because it
would give a different meaning to 'x', which is already used in a
'child' scope to denote something else.

我知道它认为这是一个范围问题,但为什么会这么想呢?

如果我在爪哇复制相同的代码,就没有问题了。


正如@blackfrog正确指出的那样,每个{ }都没有启动新的作用域。根据C语言规范第3.3节:

? Each method declaration, indexer declaration, operator declaration, instance constructor declaration and anonymous function creates a new declaration space called a local variable declaration space. Names are introduced into this declaration space through formal parameters (fixed-parameters and parameter-arrays) and type-parameters. The body of the function member or anonymous function, if any, is considered to be nested within the local variable declaration space. It is an error for a local variable declaration space and a nested local variable declaration space to contain elements with the same name.

(强调矿山)


来自msdn编译器错误cs0136

For each occurrence of a given identifier as a simple-name in an
expression or declarator, within the local variable declaration space
(§3.3) immediately enclosing that occurrence, every other occurrence
of the same identifier as a simple-name in an expression or declarator
must refer to the same entity. This rule ensures that the meaning of a
name is always the same within a given block, switch block, for-,
foreach- or using-statement, or anonymous function.

作为第二个参考,检查C答案中的变量范围混淆,您可以在中找到好的信息。

You are allowed to use the same variable name in non-overlapping
scopes. If one scope overlaps another, though, you cannot have the
same variable declared in both. The reason for that is to prevent you
from accidentally using an already-used variable name in an inner
scope


并非所有的{}都开始了新的作用域。if块中声明的整数仍与函数位于同一堆栈上。


我认为更明显的原因是,如果将x的外部声明移到if语句之上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void Main()
{
    bool result = true; // some dummy value

    int x = 10;

    if(result)
    {
        //references x in parent scope
        x = 5;
        //x is already defined, can't define again
        int x = 5;
        Console.WriteLine(x);
    }

    Console.WriteLine(x);
}

显然,编译器会将x视为一个变量,当代码试图再次声明它时,该变量已经在if语句中定义。