I faced this strange behavior when I was coding. So I ask it here.
What is the scope of a for
loop when declaring variables?
This code compiles fine
for (int i = 0; i < 10; i++) { }
for (int i = 0; i < 10; i++) { }
This means both int i
are not in same scope.
But this code does not compile.
for (int i = 0; i < 10; i++) { }
int i; // Conflicts with both first loop and second one.
for (int i = 0; i < 10; i++) { }
This means the int i
in middle of loops has the same scope of first loop and the second loop.
But how can int i
in two for
loops have different scope, but the same scope with middle int i
? Because currently I see them at the same level.
I know the second code does not compile. Why does the first code compile then if there is problem in scopes. Is this an exception inside the compiler?
The variable is within the scope of the loop. I.e. you need to be within the loop to access it. It's the same as if you declared a variable within a function, only things in the function have access to it.
Declaring Loop Control Variables Inside the for Loop, When you declare a variable inside a for loop, there is one important point to remember: the scope of that variable ends when the for statement does. (That is, the scope of the variable is limited to the for loop.)
A block is a group of zero or more statements between balanced braces and can be used anywhere a single statement is allowed. What ever the variables declared inside the block ,the scope restricted to that block. So J scope is restricted to inside that block. That is for loop.
However, the above while loop would still give an output of 3 3 3 , so the previously shown for loop can't be equivalent to it. The explanation is that a for loop has an own scope for every iteration.
The C# compiler does not check whether a variable was declared before or after another variable. All that matters is the scope. The i
variable declared between loops surely conflicts with the second loop, because if you use i
inside the loop, there is no way to distinguish which i
you'd like to use. As for the first loop, an error is still shown, because the block where i
is declared encapsulates also the first loop.
For example, the following will not compile, even though j
is not visible outside inner braces, so there should not be any ambiguity regarding i
:
{ { int i = 1; int j = 1; } int i = 0; // compiler error: A local variable i cannot be declared in this scope (...) // j is not visible here }
Edit regarding the comment:
Why is the following fine?
{ for(int i = 1; i < 10; i++) {} for(int i = 1; i < 10; i++) {} }
When you declare a for
loop variable, it is visible only inside the loop block. That means that the scopes of both variables are disjoint, since there is no line of code where one block "overlaps" the other one.
The scope of a for loop, for(INIT; COND; INCR) { BLOCK }
is identical in scoping to
{
INIT;
while (COND) {
BLOCK;
INCR;
}
}
Thus a for loop can be best thought of as two nested scopes. (Note: the above conversion from for
to while
does not properly capture the behavior of continue
. However, this question is not focused on that)
The issue you run into with the int i
outside of the for loop is something called "shadowing." In C++, if you declared a scoped variable with the same name as something in an outer scope, you "shadowed it," silently covering it up until the scope ended. When they developed C#, they felt this was too counterintuitive, and too error prone. In C# it is a syntax error to shadow a variable from an outer scope. By introducing int i
to the outer scope, it is now illegal for the for
loops to introduce it themselves.
The variable declared in for loop has just scope inside for loop block, but when you declare a variable outside for loop, you cannot have same name variable inside the for loop, because it confuses compiler that which variable you mean in for loop body.
Like i will take your code as example:
int i =0;
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is confused which i you mean here, so i complains on compile time that you have two with same name
}
So if you declare it between loops as you did, variable i
has scope in both for loops so it is accessible in both for loops, so if you remove first loop it will still complain because of global scope of variable outside the loop:
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is still confused which i you mean
}
int i =0;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With