在for-循环中声明的变量是局部变量吗?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (19)

我已经使用C#很长时间了,但从未意识到以下几点:

 public static void Main()
 {
     for (int i = 0; i < 5; i++)
     {

     }

     int i = 4;  //cannot declare as 'i' is declared in child scope                
     int A = i;  //cannot assign as 'i' does not exist in this context
 }

那么,如果For块不允许我声明具有此名称的变量,为什么不能使用For块外部的‘i’值呢?

我认为for-循环使用的迭代器变量仅在其作用域有效。

提问于
用户回答回答于

J.Kommer的回答是正确的:简单地说,局部变量在局部变量声明空间重叠另一个局部变量声明空间有一个同名的本地人。

这里还违反了C#的另一个规则。另外的规则是使用简单名称来引用两个不同重叠局部变量声明空间中的两个不同实体是非法的。所以你的例子不仅是非法的,这也是非法的:

class C
{
    int x;
    void M()
    {
        int y = x;
        if(whatever)
        {
            int x = 123;

因为现在在局部变量声明空间“y”中使用了简单的名称“x”来表示两种不同的东西--“this.x”和“local”“x”。

用户回答回答于

不允许在for-循环和for-循环之外定义同名变量的原因是,外部作用域中的变量在内部作用域中是有效的。这意味着如果允许的话,for-循环中将有两个‘i’变量。

具体而言:

局部变量声明中声明的局部变量范围(第8.5.1节)是声明发生的块。

在for语句的for-初始化器(第8.8.3节)中声明的局部变量的作用域是for-初始化器、for-条件、for-迭代器和for语句的包含语句。

具体而言:

在局部变量声明中声明的局部变量的作用域是发生声明的块。在局部变量的局部变量声明符之前的文本位置引用局部变量是错误的。在局部变量范围内,声明另一个局部变量或同名常量是编译时错误。

这意味着i在的for-循环中,是for-循环。鉴于i在for-循环之外是整个主要方法。那个循环。意味着你会有两次i在循环内部,根据上述情况,该循环是无效的。

你不被允许这么做的原因int A = i;是因为int i对象的作用域,以便在for循环。因此,在for循环。

如您所见,这两个问题都是范围界定的结果;第一个问题(int i = 4;)将产生两个i中的变量。for循环范围。鉴于int A = i;将导致对超出作用域的变量的访问。

相反,你可以做的是声明i将作用域限定为整个方法,然后在方法和for-循环作用域中使用它。这将避免违反任何一条规则。

public static void Main()
{
    int i;

    for (i = 0; i < 5; i++)
    {

    }

    // 'i' is only declared in the method scope now, 
    // no longer in the child scope -> valid.
    i = 4;

    // 'i' is declared in the method's scope -> valid. 
    int A = i;
}

当然,可以更改C#编译器,以使该代码能够非常有效地编译。所有这些都是有效的:

for (int i = 0; i < 5; i++)
{
    Console.WriteLine(i);
}

for (int i = 5; i > 0; i--)
{
    Console.WriteLine(i);
}

但是,能够编写这样的代码真的对代码的可读性和可维护性有好处吗?

public static void Main()
{
    int i = 4;

    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine(i);
    }

    for (int i = 5; i > 0; i--)
    {
        Console.WriteLine(i);
    }

    Console.WriteLine(i);
}

想一想这里可能会出现的错误,最后一个是吗?i打印0还是4?这是一个非常小的例子,它很容易跟踪和跟踪,但它肯定比声明外部的更难维护和可读性更低。i用不同的名字。

扫码关注云+社区