variable scope in statement blocks

前端 未结 9 1826
梦如初夏
梦如初夏 2020-12-01 21:14
for (int i = 0; i < 10; i++)
{
    Foo();
}
int i = 10; // error, \'i\' already exists

----------------------------------------    

for (int i = 0; i < 10; i         


        
相关标签:
9条回答
  • 2020-12-01 21:57

    From the C# spec on local variable declarations:

    The scope of a local variable declared in a local-variable-declaration is the block in which the declaration occurs.

    Now, of course, you can't use i before it is declared, but the i declaration's scope is the entire block that contains it:

    {
        // scope starts here
        for (int i = 0; i < 10; i++)
        {
            Foo();
        }
        int i = 10;
    }
    

    The for i variable is in a child scope, hence the collision of variable names.

    If we rearrange the position of the declaration, the collision becomes clearer:

    {
        int i = 10;
    
        // collision with i
        for (int i = 0; i < 10; i++)
        {
            Foo();
        }
    }
    
    0 讨论(0)
  • 2020-12-01 21:57
    class Test
    {
        int i;
        static int si=9; 
    
        public Test()
        {
            i = 199;
        }
    
        static void main()
        {
            for (int i = 0; i < 10; i++)
            {
                var x = 2;
            }
    
            { var x = 3; }
    
            {    // remove outer "{ }" will generate compile error
                int si = 3; int i = 0;
    
                 Console.WriteLine(si);
                 Console.WriteLine(Test.si);
                 Console.WriteLine(i);
                 Console.WriteLine((new Test()).i);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-01 22:01

    Yea, I second the "nanny-state compilerism" comment. What's interesting is that this is ok.

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

    and this is ok

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

    but this is not

    for (int i = 0; i < 10; i++)
    {
        var x = 2;
    }
    
    var x = 5;
    

    even though you can do this

    for (int i = 0; i < 10; i++)
    {
        var k = 12;
    }
    
    for (int i = 0; i < 10; i++)
    {
        var k = 13;
    }
    

    It's all a little inconsistent.

    EDIT

    Based on the comment exchange with Eric below, I thought it might be helpful to show how I try to handle loops. I try to compose loops into their own method whenever possible. I do this because it promotes readability.

    BEFORE

    /*
     * doing two different things with the same name is unclear
     */
    for (var index = 0; index < people.Count; index++)
    {
        people[index].Email = null;
    }
    var index = GetIndexForSomethingElse(); 
    

    AFTER

    /*
     * Now there is only one meaning for index in this scope
     */
    ClearEmailAddressesFor(people); // the method name works like a comment now
    var index = GetIndexForSomethingElse();
    
    /*
     * Now index has a single meaning in the scope of this method.
     */
    private void ClearEmailAddressesFor(IList<Person> people)
    {
        for (var index = 0; index < people.Count; index++)
        {
            people[index].Email = null;
        }
    }
    
    0 讨论(0)
  • 2020-12-01 22:03

    It is because the declaration space defines i at the method level. The variable i is out of scope at the end of the loop, but you still can't redeclare i, because i was already defined in that method.

    Scope vs Declaration Space:

    http://csharpfeeds.com/post/11730/Whats_The_Difference_Part_Two_Scope_vs_Declaration_Space_vs_Lifetime.aspx

    You'll want to take a look at Eric Lippert's answer (who by default is always right concerning questions like these).

    http://blogs.msdn.com/ericlippert/archive/2009/08/03/what-s-the-difference-part-two-scope-vs-declaration-space-vs-lifetime.aspx

    Here is a comment from eric on the above mentioned post that I think talks about why they did what they did:

    Look at it this way. It should always be legal to move the declaration of a variable UP in the source code so long as you keep it in the same block, right? If we did it the way you suggest, then that would sometimes be legal and sometimes be illegal! But the thing we really want to avoid is what happens in C++ -- in C++, sometimes moving a variable declaration up actually changes the bindings of other simple names!

    0 讨论(0)
  • 2020-12-01 22:07

    In the first example, the declaration of i outside of the loop makes i a local variable of the function. As a result, it is an error to have another variable name i declared within any block of that function.

    The second, i is in scope only during the loop. Outside of the loop, i can no longer be accessed.

    So you have seen the errors, but there is nothing wrong with doing this

    for (int i = 0; i < 10; i++)
    {
      // do something
    }
    
    foreach (Foo foo in foos)
    {
       int i = 42;
       // do something 
    }
    

    Because the scope of i is limited within each block.

    0 讨论(0)
  • 2020-12-01 22:10

    you need to do

                int i ;
                for ( i = 0; i < 10; i++)
                {
    
                }
                i = 10;
    
    0 讨论(0)
提交回复
热议问题