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.
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:
and
And also: Local variable declarations (Section 8.5.1 of the C# specification)
Specifically:
(Emphasis mine.)
Which means that the scope of the
iinside your for-loop, is the for-loop. Whereas the scope of theioutside of your for-loop is the entire main method plus the for-loop. Meaning you’d have two occurrences ofiinside the loop which is invalid according to the above.The reason why you’re not allowed to do
int A = i;is becauseint iis only scoped for use within theforloop. Thus it is no longer accessible outside of theforloop.As you can see both of these issues are a result of scoping; the first issue (
int i = 4;) would result in twoivariables within theforloop scope. Whereasint A = i;would result in access to a variable that is out of scope.What you could do instead is declare
ito 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.EDIT:
The C# compiler could of course be changed to allow this code to compile quite validly. After all this is valid:
But would it really be beneficial to your code readability and maintainability to be able to write code such as:
Think about the potential for mistakes here, does the last
iprint 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 outeriby 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++.