Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable declared in for-loop is local variable?

I have been using C# for quite a long time but never realised the following:

 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
 }

So why can I not use the value of 'i' outside of the for block if it does not allow me to declare a variable with this name?

I thought that the iterator variable used by a for-loop is valid only in its scope.

like image 899
John V Avatar asked Nov 03 '11 09:11

John V


People also ask

Are variables in for loops local?

A local loop variable is one that exists only when the Loop Facility is invoked. At that time, the variables are declared and are initialized to some value. These local variables exist until loop iteration terminates, at which point they cease to exist.

Are variables in loops local or global?

For the most part, loops do not have their own scope, so the variable's scope will be the scope of wherever the for loop lives. With that in mind, if the for loop is within a function, it will have local scope.

Can you declare variables in a for loop?

Often the variable that controls a for loop is needed only for the purposes of the loop and is not used elsewhere. When this is the case, it is possible to declare the variable inside the initialization portion of the for.

Are variables in for loops local Python?

In Python, on the other hand, variables declared in if-statements, for-loop blocks, and while-loop blocks are not local variables, and stay in scope outside of the block. Thus we say that C++ has “block-level” scoping, while Python uses only “function-level” scoping.


Video Answer


3 Answers

The reason you are not allowed to define a variable with the same name in both the for-loop as well as outside the for-loop is because variables in the outer-scope are valid in the inner-scope. Meaning that there would be two 'i' variables within the for-loop if this was allowed.

See: MSDN Scopes

Specifically:

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

and

The scope of a local variable declared in a for-initializer of a for statement (Section 8.8.3) is the for-initializer, the for-condition, the for-iterator, and the contained statement of the for statement.

And also: Local variable declarations (Section 8.5.1 of the C# specification)

Specifically:

The scope of a local variable declared in a local-variable-declaration is the block in which the declaration occurs. It is an error to refer to a local variable in a textual position that precedes the local-variable-declarator of the local variable. Within the scope of a local variable, it is a compile-time error to declare another local variable or constant with the same name.

(Emphasis mine.)

Which means that the scope of the i inside your for-loop, is the for-loop. Whereas the scope of the i outside of your for-loop is the entire main method plus the for-loop. Meaning you'd have two occurrences of i inside the loop which is invalid according to the above.

The reason why you're not allowed to do int A = i; is because int i is only scoped for use within the for loop. Thus it is no longer accessible outside of the for loop.

As you can see both of these issues are a result of scoping; the first issue (int i = 4;) would result in two i variables within the for loop scope. Whereas int A = i; would result in access to a variable that is out of scope.

What you could do instead is declare i to be scoped to the entire method, and then use it in both the method as well as the for-loop scope. This will avoid breaking either rule.

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;
}

EDIT:

The C# compiler could of course be changed to allow this code to compile quite validly. After all this is valid:

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

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

But would it really be beneficial to your code readability and maintainability to be able to write code such as:

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);
}

Think about the potential for mistakes here, does the last i print out 0 or 4? Now this is a very small example, one which is quite easy to follow and track but it is definitely a lot less maintainable and readable than having declared the outer i by a different name.

N.B:

Please note, C#'s scoping rules differ from C++'s scoping rules. In C++ variables are only in scope from where they are declared until the end of the block. Which would make your code a valid construct in C++.

like image 62
Johannes Kommer Avatar answered Oct 12 '22 20:10

Johannes Kommer


J.Kommer's answer is correct: briefly, it is illegal for a local variable to be declared in a local variable declaration space that overlaps another local variable declaration space that has a local of the same name.

There is an additional rule of C# that is violated here as well. The additional rule is that it is illegal for a simple name to be used to refer to two different entities inside two different overlapping local variable declaration spaces. So not only is your example illegal, this is illegal too:

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

Because now the simple name "x" has been used inside the local variable declaration space of "y" to mean two different things -- "this.x" and the local "x".

See http://blogs.msdn.com/b/ericlippert/archive/tags/simple+names/ for more analysis of these issues.

like image 29
Eric Lippert Avatar answered Oct 12 '22 20:10

Eric Lippert


There is a way of declaring and using i inside the method after the loop:

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

    }

    {
        int i = 4;
        int A = i;
    }
}

You can do this in Java (it might originate from C I'm not sure). It is of course a bit messy for the sake of a variable name.

like image 13
Chris S Avatar answered Oct 12 '22 21:10

Chris S