关于.NET:c# foreach变量范围

C# foreach variable scope

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

我用c foreach循环遇到了一个奇怪的问题,我不知道为什么。有人能解释一下这个代码有什么问题吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        var previouslyLoadedControls = ComposantPanel.Controls.OfType<GridView>().Where(x => x.Rows.Count > 0);

        foreach (var gridView in previouslyLoadedControls)
        {
            gridView.DataSource = null;
            gridView.DataBind();
        }

        var gridViewId ="GridViewOne";
        var gridView = (GridView)ComposantPanel.FindControl(gridViewId);

        gridView.DataSource = objects;
        gridView.DataBind();
        gridView.Visible = true;

编译器告诉我"不能在此作用域中声明名为"gridview"的局部变量,因为它将给"gridview"赋予不同的含义,该"gridview"已在"child"作用域中用于表示"at line"var gridview=(gridview)composeantpanel.findcontrol(gridviewid);"

为什么第一个gridview变量不只能在foreach循环范围内访问?

如果我只是把第二个gridview声明注释掉,编译器会告诉我"gridview.datasource=objects;"的当前上下文中不存在"gridview"的名称。那么foreach变量的作用域是什么呢?

我开始读一些关于关闭的arciles(http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/和http://csharpindepth.com/articles/chapter5/closures.aspx),但我还是不明白。

我使用vs 2013与.NET 4.5.1和C_5。


Why isn't the first gridView variable only accessible in the foreach loop scope ?

是的,但是编译器(语言定义)只是禁止重叠的作用域。

产生相同错误的简化版本:

1
2
3
4
5
6
7
8
9
{   // outer block, scope for the second `i`

    for(int i = 0; i < 10; i++)  // nested 'i', the first we see
    {
       // scope of first `i`  
    }

    int i = 3;  // declaration of a second `i`, not allowed
}

这很难理解get的原因是第二个"i"只能在其声明之后使用,但其作用域是整个外部块。

见C语言规范和第3.7节:范围


您提到的已经阅读过的文章在这里是不相关的,因为您没有一个循环变量的闭包。

发生的情况是在封闭范围中有一个同名的变量。这是不允许的(至少对于方法中开始的作用域)。如果您尝试在for循环中声明gridView,或者只声明一个嵌套块,则会遇到同样的问题。

但是,可以使用相同的变量名让两个循环相邻,因为它们不重叠。还要注意,变量范围是由块决定的,即使只有在声明了它们之后才能访问它们。这意味着即使您的foreach循环在您声明第二个gridView变量之前,它们的作用域也会重叠。