2

I ran in a strange problem using C# foreach loop and I don't get why. Can somebody explains me what is wrong with this code ?

        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;

Compiler tells me "A local variable named 'gridView' cannot be declared in this scope because it would give a different meaning to 'gridView', which is already used in a 'child' scope to denote something else" at line "var gridView = (GridView)ComposantPanel.FindControl(gridViewId);"

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

And if I just comment the second gridView declaration out then compiler tells me "The name 'gridView' does not exist in the current context" at "gridView.DataSource = objects;". So what is the scope of my foreach variable ?

i started to read some arciles (http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/ and http://csharpindepth.com/Articles/Chapter5/Closures.aspx) about closure but I still don't get it.

I use VS 2013 with .Net 4.5.1 and C# 5.

  • See duplicate for an even smaller example and the same answer: _"the scope for the "later" variable includes the part of the block before the declaration - i.e. it includes the "inner" block containing the "earlier" variable."_. – CodeCaster Jun 05 '15 at 09:37

2 Answers2

1

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

It is, but the compiler (language definition) simply forbids overlapping scopes.

A simplified version that yields the same error:

{   // 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
}

The reason this is hard to read an get is that the second 'i' may only be used after its declaration, but its scope is the entire outer block.

See C# Language specification, § 3.7: Scopes

H H
  • 263,252
  • 30
  • 330
  • 514
0

The articles you mention to have read are irrelevant here, as you do not have a closure over the loop variable.

What happens is that you have a variable of the same name in the enclosing scope. This is not allowed (at least for scopes starting in methods). You have the same problem if you'd try declaring gridView in a for loop or just a nested block.

You can have two loops next to each other using the same variable name, though, since they don't overlap. Note also that variable scope is determined by blocks, even though you can access them only after they have been declared. That means that even though your foreach loop is before you declare the second gridView variable, their scopes do overlap.

Joey
  • 344,408
  • 85
  • 689
  • 683