【问题标题】:Scope of a 'for' loop at declaration of a variable声明变量时“for”循环的范围
【发布时间】:2015-11-29 01:23:30
【问题描述】:

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

声明变量时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 与第一个循环和第二个循环的范围相同。

但是两个for 循环中的int i 怎么可能有不同的作用域,而中间的int i 的作用域相同呢?因为目前我看到他们处于同一水平。

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

【问题讨论】:

  • 不在同一个范围内,而是在一个嵌套的范围内,这也是被禁止的。看看这个问题以获得类似问题的答案:stackoverflow.com/questions/6156449/…
  • 有趣的是,for(int i = ...) {} {int i; } for(int i = ...) {}(注意内部{})确实符合要求。
  • @DmitryBychenko:这是因为 i 仅存在于大括号定义的块内(在 for 循环之间)。
  • 外部i 是在第一个for 循环之前还是之后都没有关系。编译器不想要它。观点。如果将声明从下到上移动,编译器错误可以防止您出现粗心的错误。这很容易避免。
  • 由于没有答案表明:假设This means the int i in middle of loops has the same scope of first loop and the second loop. 是错误的,这是这里的主要问题。

标签: c# for-loop scope


【解决方案1】:

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 循环变量时,它仅在循环块内可见。这意味着两个变量的范围是不相交的,因为没有一行代码会“重叠”另一个块。

【讨论】:

  • 是的。确定它与第二个循环冲突,但是这个也不能编译。 for (int i = 0; i &lt; 10; i++) { }int i;。但是for (int i = 0; i &lt; 10; i++) { }for (int i = 0; i &lt; 10; i++) { }怎么可能呢?
  • @M.kazemAkhgary 正如大多数答案所解释的那样,变量的范围从它的声明开始,它是整个块。 for 循环定义了一个块
  • 感谢您的回答。所以它就像{int i; } { int i; } 这是可能的。
  • @M.kazemAkhgary 是的,你可以这样看。
  • 等等,这不只是意味着局部变量不能遮蔽外部变量,而且声明范围是整个块,而不仅仅是写入和转发的点?简单地说for (int i; ...) int i;int i; for (int i; ..) 相同,所有这些都会更清楚。
【解决方案2】:

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

for 语句中声明的变量循环本地的,但您已经在外部范围内定义了另一个同名变量。

假设变量的范围从声明点开始,我认为您已经提出了另一个范围界定问题?

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

【讨论】:

  • 其实OP的代码和第一个for循环有冲突,你没有解释。
  • @Shaharyar 实际上,我写了 - 我写的是内部和外部循环,而不是第一个或第二个。外部与 both 循环冲突。评论其中任何一个,你会发现你仍然有冲突。这就是为什么我没有指定一个或另一个循环
  • 在某种意义上,一个变量在被声明之前并不“在范围内”。在声明之前不能使用i。这种行为可能是编译器团队最简单的实现。不过编译器很难,所以我不怪他们。
【解决方案3】:

我认为将int i; 放在哪里并不重要。

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      在for循环中声明的变量只有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;
      

      【讨论】:

      • 不是这样的,你搞错了。 OP 表示它与第一个循环中的 i 声明冲突。您应该尝试编译 OP 的代码。
      • for (int i = 0; i &lt; 10; i++) { } int i = 20; 为什么编译器会混淆??
      • 它是全局的,无论是在循环之前还是之后编写,点在循环之外变量对两个循环都具有全局范围
      • @Shaharyar 只要在同一范围内,声明“I”的位置无关紧要。可能是之前也可能是之后,C#不会从上到下编译。
      • @RyanSearle 感谢您将其添加到我的知识中:)
      【解决方案6】:

      for 循环的范围,for(INIT; COND; INCR) { BLOCK } 的范围相同

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

      因此,最好将 for 循环视为两个嵌套范围。 (注意:上述从forwhile 的转换并没有正确捕捉到continue 的行为。但是,这个问题并不专注于此)

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

      【讨论】:

      • 很好地提到了替代范围。我想在我的回答中包含这个细节,但我不记得 for 到底是怎么翻译的。
      猜你喜欢
      • 1970-01-01
      • 2016-10-22
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多