10

I get the following error in Visual Studio 2008:

Error 1 A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else

This is my code:

for (int i = 0; i < 3; i++)
{
  string str = "";
}

int i = 0; // scope error
string str = ""; // no scope error

I understand that str ceases to exist once the loop terminates, but I also thought that the scope of i was confined to the for loop as well.

So i has the same scope as a variable declared just outside of the for loop?

Edit:

Just to be clear, I am using C#. I am debating removing the "C" tag. However, since the correct answer explains the difference between the two, I figure it makes sense to leave both tags.

I had an error in my code comment above:

for (int i = 0; i < 3; i++)
{
  string str = "";
}

int i = 0; // scope error
string str = ""; // also scope error,
                 // because it's equivalent to declaring
                 // string str =""; before the for loop (see below)
JohnB
  • 18,046
  • 16
  • 98
  • 110
  • 2
    You have tagged this c# and c. Which language are you asking about? The answer might be different, depending on which language you mean. – James McNellis Aug 06 '10 at 18:57
  • 2
    See http://stackoverflow.com/questions/2693138/variable-scope-in-statement-blocks for the same question with a great answer from Eric Lippert. Also see http://stackoverflow.com/questions/1196941/confused-with-the-scope-in-c and http://stackoverflow.com/questions/2059210/using-a-variable-name-used-in-a-child-scope – jloubert Aug 06 '10 at 19:20
  • 1
    Just to be clear, there's no problem with tagging this both `c#` and `c` (or `c++`), IF you started out with *I get the following error in C# 3.0 (Visual Studio 2008)...* and later *How are the C# rules for for-loop scoping different from ANSI C?*, which seems to be what you intended. But you didn't specify anywhere in the original question what language you were using, in which case most people look to the tags... that's where the problem with two language tags develops. – Ben Voigt Aug 06 '10 at 20:26

4 Answers4

21

I think you're all confusing C++ and C#.

In C++, it used to be that the scope of a variable declared in a for expression was external to the block that followed it. This was changed, some time ago, so that the scope of a variable declared in a for expression was internal to the block that followed it. C# follows this later approach. But neither has anything to do with this.

What's going on here is that C# doesn't allow one scope to hide a variable with the same name in an outer scope.

So, in C++, this used to be illegal. Now it's legal.

for (int i; ; )
{
}
for (int i; ; )
{
}

And the same thing is legal in C#. There are three scopes, the outer in which 'i' is not defined, and two child scopes each of which declares its own 'i'.

But what you are doing is this:

int i;
for (int i; ; )
{
}

Here, there are two scopes. An outer which declares an 'i', and an inner which also declares an 'i'. This is legal in C++ - the outer 'i' is hidden - but it's illegal in C#, regardless of whether the inner scope is a for loop, a while loop, or whatever.

Try this:

int i;
while (true)
{
    int i;
}

It's the same problem. C# does not allow variables with the same name in nested scopes.

Jeff Dege
  • 11,190
  • 22
  • 96
  • 165
  • 10
    **This** is the correct answer. C# doesn't let you hide variables because it can be confusing. C++ doesn't care. It has nothing to do with `for` loop syntax, or whether variables are declared at the top or bottom of the function, or anything else... – John Kugelman Aug 06 '10 at 19:15
  • 1
    I've found that actually reading the error message is sometimes helpful. – Jeff Dege Aug 06 '10 at 19:24
3

The incrementor does not exist after the for loop.

for (int i = 0; i < 10; i++) { }
int b = i; // this complains i doesn't exist
int i = 0; // this complains i would change a child scope version because the for's {} is a child scope of current scope

The reason you can't redeclare i after the for loop is because in the IL it would actually declare it before the for loop, because declarations occur at the top of the scope.

Jimmy Hoffa
  • 5,909
  • 30
  • 53
2

Yea. Syntactically: The new scope is inside the block defined by the curly strings. Functionally: There are cases in which you may want to check the final value of the loop variable (for example, if you break).

Nicolas78
  • 5,124
  • 1
  • 23
  • 41
2

Just some background information: The sequence doesn't come into it. There's just the idea of scopes - the method scope and then the for loop's scope. As such 'once the loop terminates' isn't accurate.

You're posting therefore reads the same as this:

int i = 0; // scope error
string str = ""; // no scope error

for (int i = 0; i < 3; i++)
{
  string str = "";
}

I find that thinking about it like this makes the answers 'fit' in my mental model better..

Kieren Johnstone
  • 41,277
  • 16
  • 94
  • 144
  • +1 Thanks and great point! That clears things up even better! (but doesn't directly answer my question, so you don't get the check) – JohnB Aug 06 '10 at 18:58
  • 1
    The double declaration of `str` is fine in C++ but it's a scoping error in C#. The problem in the OP's question is not about having two variables declared in the *same* scope, it's that C# doesn't let you have the same variable in *nested* scopes because it could be confusing. C++ let's you do the confusing thing. – John Kugelman Aug 06 '10 at 19:12
  • 1
    John, sure, but what was it that you said that made my answer inappropriate or unhelpful (assuming you voted me down)? As I said, it's some background information, and as the OP said, 'Thanks and great point! That clears things up even better'. – Kieren Johnstone Aug 06 '10 at 19:48
  • 1
    The two `str` variables *do* cause an error in C#, just like the two `i` variables do. And neither one causes an error in C++. Your code snippet is wrong in either language. I don't mean to pile on, but I think your answer added to the OP's confusion rather than clearing it up. – John Kugelman Aug 06 '10 at 20:07
  • @John Kugelman: it was my fault for saying `string str = ""; // no scope error` initially. However, Kieren really nailed why I was getting my error first (which is because the sequence is reversible to the compiler). However, I'm giving the check to Jeff Dege because he provided a clearer answer. – JohnB Aug 06 '10 at 20:28
  • @John Kugelman - No, I wasn't saying that was valid code. Read the question again. I said 'your posting therefore reads the same as this'. And the original posting has the error, so I was re-iterating the same code, but with the lines moved. I wasn't suggesting a solution. Please re-read answers before you decide to vote them down; you are wrong. – Kieren Johnstone Aug 06 '10 at 21:21