声明变量时'for'循环的范围

时间:2015-09-03 09:23:50

标签: c# for-loop scope

我在编码时遇到了这种奇怪的行为。所以我在这里问。

声明变量时for循环的范围是什么?

此代码编译正确

for (int i = 0; i < 10; i++) { }

for (int i = 0; i < 10; i++) { }

这意味着两个int i不在同一范围内。

但是这段代码没有编译。

for (int i = 0; i < 10; i++) { }
int i; // Conflicts with both first loop and second one.
for (int i = 0; i < 10; i++) { }

这意味着循环中间的int i具有与第一个循环和第二个循环相同的范围。

但两个int i循环中的for如何具有不同的范围,但中间int i的范围相同?因为目前我看到它们处于同一水平。

我知道第二个代码无法编译。如果范围存在问题,为什么第一个代码会编译。这是编译器内部的异常吗?

6 个答案:

答案 0 :(得分:24)

C#编译器不检查变量是在另一个变量之前还是之后声明。重要的是范围。在循环之间声明的i变量肯定与第二个循环冲突,因为如果在循环中使用i,则无法区分您想要使用的i。至于第一个循环,仍会显示错误,因为声明i的块也封装了第一个循环。

例如,即使j在内括号外部不可见,也不会编译以下内容,因此i不应该有任何歧义:

{
    {
        int i = 1;
        int j = 1;
    }

    int i = 0; // compiler error: A local variable i cannot be declared in this scope (...)
    // j is not visible here
}

关于评论的修改:

为什么以下罚款?

{
    for(int i = 1; i < 10; i++) {}
    for(int i = 1; i < 10; i++) {}
}

当您声明for循环变量时,它仅在循环块中可见。这意味着两个变量的范围是不相交的,因为没有代码行,其中一个块“重叠”另一个块。

答案 1 :(得分:7)

for循环的范围for(INIT; COND; INCR) { BLOCK }在范围界定方面相同

{
    INIT;
    while (COND) {
        BLOCK;
        INCR;
     }
 }

因此,for循环最好被认为是两个嵌套的范围。 (注意:上述从forwhile的转换无法正确捕获continue的行为。但是,这个问题并没有集中在那个问题上)

在for循环之外遇到int i的问题就是所谓的“阴影”。在C ++中,如果您声明了一个与外部作用域中的某个名称相同的作用域变量,那么您“隐藏它”,默默地覆盖它直到作用域结束。当他们开发C#时,他们觉得这太违反直觉了,而且容易出错。在C#中,从外部作用域遮蔽变量是一种语法错误。通过将int i引入外部作用域,for循环现在自行引入它是非法的。

答案 2 :(得分:3)

在for循环中声明的变量只包含for循环块的范围,但是当你在for循环外声明一个变量时,你不能在for循环中使用相同的名称变量,因为它会混淆编译器你在循环中使用哪个变量体。

就像我会以你的代码为例:

int i =0;
for (int i = 0; i < 10; i++) 
{
  i = i+1; // now compiler is confused which i you mean here, so i complains on compile time that you have two with same name
}

因此,如果你像循环一样在循环之间声明它,变量i在两个for循环中都有范围,因此它可以在两个for循环中访问,所以如果你删除第一个循环,它仍然会因为全局范围而抱怨循环外的变量:

for (int i = 0; i < 10; i++) 
{
  i = i+1; // now compiler is still confused which i you mean 
}
int i =0;

答案 3 :(得分:2)

没有什么奇怪的事情发生。在第二种情况下,您已经定义了外部 i,然后尝试在每个循环中重新定义它。

for语句中声明的变量是循环的本地变量,但是您已经在外部作用域中定义了另一个具有相同名称的变量。

我认为你已经问过另一个范围问题,假设变量的范围从声明的角度开始?

变量的范围是定义它的块,它不受其放置的影响。虽然编译器将拒绝在声明之前使用该变量,但它仍在范围内

答案 4 :(得分:2)

我认为你把int i;放在哪里很重要。

编译器首先扫描该字段,然后开始扫描表达式。它没有编译,因为i已被识别为字段。

答案 5 :(得分:1)

int i;您在循环外声明可用于当前函数。要么只声明外部int i,要么从两个循环中删除int i,要么只删除这个外部变量。