Why can't I use the same variable as an inner loop does?

Why can't I use the same variable as an inner loop does?

  • Comments 12

Q: Why can't I do the following:

namespace Bug

{

            class Class1

            {

                        [STAThread]

                        static void Main(string[] args)

                        {

                                    for(int i=0; i<100; i++)

                                    {

 

                                    }

 

                                    int i = 0;

                        }

            }

}

the compiler gives me an error on the “int i = 0;” part of the code.

A: This is correct behavior, and is covered in section 3.7 of the language spec. It says, “The scope of a local variable declared in a local-variable-declaration (8.5.1) is the block in the which the declaration occurs”.

The scope of i is therefore the entire Main() function, and that means that the use in the for loop is a re=use, and therefore is not allowed.

This behavior is inteded to make incorrect re-use of variable names (such as in a cut and paste) less likely.

[Author: Eric Gunnerson]

Leave a Comment
  • Please add 5 and 2 and type the answer here:
  • Post
  • This really isn't a big problem. In fact, it has saved myself and some others I know several times from screwing up the value of local variables by reusing them inside a loop.

    Btw, the C# Team FAQ blog is great. I look forward to all sorts of new posts on my (current) favorite programming language.
  • Two uses of i:
    child scope in the for loop
    function local scope just after the for loop

    Now, you say that the use inside of the for-loop is the re-use, since even though we declare i at the bottom of the method, it has scope for the entire method. I can live with that. However, you output an error saying that the second use (the function local) is a redefinition of i in the child scope.

    So while function local variables have function scope, they don't have function visibility. I can't define a variable at the end of my function but make use of it in the beginning even though the definition at the end gives the variable function scope.

    Intrinsically this makes a large amount of sense to parse variables in front to back order and only make them visible for areas of the function in which they are defined. However, you don't really know the flow of the method in advance. Take this rather contrived example that fails in the C# compiler:

    namespace Bug {
    class Class1 {
    static void Main(string[] args) {
    goto variable_definitions;
    function:

    for(i=0; i<100; i++) { }

    goto end;

    variable_definitions:
    int i = 0;
    goto function;

    end:

    return;
    }
    }
    }

    I'm guessing some of the same semantics that are at play here also prevent the re-use of local variable slots in for nested scope variables that have the same type.

    http://weblogs.asp.net/justin_rogers/archive/2004/02/16/73627.aspx
  • Same goes for the switch statement.

    swith (a)
    {
    case b:
    for (int i = 1; i<=10; i++)
    {
    Console.WriteLine("Do this 10 times")
    }
    break;
    case c:
    for (int i = 1; i<=20; i++)
    {
    Console.WriteLine("Do this 20 times")
    }
    break;
    case d:
    Object myObject = new Object();
    myObject.DoSomething();
    break;
    case e:
    Object myObject = new Object();
    myObject.DoSomethingElse();
    break;
    }

    Doesn't work either... Kinda sucks, but I think it's for the best! :)

    In case e, the variable is already declared, according to the compiler, in case d.
  • I don't get it. The variable is not visible outside the for loop, how can it belong to the main block?

    My intuition says 'i' also is a member of the for block. It is not visible outside of it, hence it can't be used, so reuse should be allowed.

    There is simply not possible to use it incorrectly.
  • <blush>
    My mistake. The latter 'i' does of course belong to the main block. So it does make sense
    </blush>
  • namespace Bugx
    {
    Class Class1
    {
    [STAThread]
    static void Main(string[] args)
    {
    for( int i=0; i<100; i++){
    }
    for( int i=0; i<100; i++){
    //Why is right here?
    }
    {
    //right here?
    int i = 0;
    }
    int i =0 ; //why is error here?
    }
    }
    }
  • Believe you, support you, I believe that you are right! ! ! I will make great efforts to look like your study! ! !
  • [http://itpeixun.51.net/][http://aissl.51.net/][http://kukuxz003.freewebpage.org/][http://kukuxz001.51.net/][http://kukuxz003.51.net/][http://kukuxz005.51.net/][http://kukuxz002.51.net/][http://kukuxz004.freewebpage.org/][http://kukuxz007.51.net/][http://kukuxz001.freewebpage.org/][http://kukuxz006.51.net/][http://kukuxz002.freewebpage.org/][http://kukuxz004.51.net/][http://kukuxz008.51.net/][http://kukuxz009.51.net/][http://kukuxz005.freewebpage.org/][http://kukuxz006.freewebpage.org/][http://kukuxz007.freewebpage.org/][http://kukuxz009.freewebpage.org/]
  • Why, then, is the following valid...

         for (int i=0; i<example.Length; ++i) Console.WriteLine("Firet: "+example [i]);

         for (int i=0; i<example.Length; ++i) Console.WriteLine(example [i]);

    Please answer ASAP

  • @Rajesh Patel:

    Yes, the way you use is correct. It's 2 different child scope. Here is an example:

               for (int i = 0; i < 100; i++)

               {

                   // Correct here. Child scope

                   Console.WriteLine(i);

               }

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

               {

                   // Correct here. Child Scope

                   Console.WriteLine(i);

               }

               {

                   // Correct here. Child Scope

                   int i = 0;

                   Console.WriteLine(i);

               }

               // Error here. Main Scope

               int i = 20;

  • I have arrived here a couple of years later, I know, but I would just like to point out that this is a pretty stupid rule. Can we use the external "i" before the for loop? Nope. Because it was not declared yet. Can we use the innermost "i" (the one declared in the for()) after the for loop scope ends? No, because the variable scope has ended right there.

    What I would concede to is IF, AND ONLY IF, a warning was issued if you declared the outer "i" before that for loop. Then I can see a possible screw up. Even though whoever writes codes like that would be asking for it, the rule should quite simple: the one in the most restrictive scope is the valid one. But a nice warning would be great there.

    Otherwise we can simply go back to the C days, where we h

  • because you are declaring i twice in the same block of code ie main.  you are declaring in a loop than again after the loop.  if you change the 2nd to i=0 it will compile.

Page 1 of 1 (12 items)