Variable vs. child scopes

G

Guest

Hi,

When I try to compile the below code snippet, I get the compile error listed
below in this question. In the lines below the loop, the variable j does not
excist, however, trying to create it is not allowed. If it doesn't excist,
why can't I create it?.

I'm not looking for a solution to this problem - that's quite easy - an
explanation however would be great, as I've been intrigued by this for a
couple of years now.

Thanks Jesper.

Code snippet.

int foo = 0;

for (int j = 0; j < 5; j++)
{
foo += j;
}

int j = 5;


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

Jon Skeet [C# MVP]

Jesper said:
When I try to compile the below code snippet, I get the compile error listed
below in this question. In the lines below the loop, the variable j does not
excist, however, trying to create it is not allowed. If it doesn't excist,
why can't I create it?.

I'm not looking for a solution to this problem - that's quite easy - an
explanation however would be great, as I've been intrigued by this for a
couple of years now.

The scope of a variable is the whole of the block it's declared in,
even though it's not available before it's declared.

From the Unified C# 3 spec, section 3.7:

<quote>
The scope of a local variable declared in a local-variable-declaration
(§8.5.1) is the block in which the declaration occurs.
</quote>
 
G

Guest

Jesper said:
Hi,

When I try to compile the below code snippet, I get the compile error listed
below in this question. In the lines below the loop, the variable j does not
excist, however, trying to create it is not allowed. If it doesn't excist,
why can't I create it?.

I'm not looking for a solution to this problem - that's quite easy - an
explanation however would be great, as I've been intrigued by this for a
couple of years now.

Thanks Jesper.

Code snippet.

int foo = 0;

for (int j = 0; j < 5; j++)
{
foo += j;
}

int j = 5;


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

A variable in a child scope is not allowed to have the same name as a
variable in the parent scope. Not because the compiler wouldn't be able
to figure it out, but because the code would very easily become
confusing to humans.

Take a simple example where you use a variable in a loop:

int j = 1;
for (int i = 0; i < 10; i++) {
Console.WriteLine(j);
j = 1 - j;
}

If you would change the code to write each value more than once, and
were allowed to use the same variable name i child scope, you could do:

int j = 1;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 3; j++) {
Console.WriteLine(j);
}
j = 1 - j;
}

This would of course not give the desired result. The code for the
output hasn't changed, but the meaning of the variable has changed. In a
more complex code, it could be very hard to spot the cause of the problem.
 
R

Rene

In the example below, both "i" variables are limited in scope by the "{}"
braces (they don't conflict with each other).

static void Main(string[] args)
{
{
int i = 123;
Console.WriteLine(i.ToString());
}

{
int i = 456;
Console.WriteLine(i.ToString());
}
}

I believe the compiler uses this technique to guaranty that the "j" variable
on your loop does not interfere with other variables in you code scoped at
the same level (such as having another exact same loop on the same function)
, so basically the compiler is doing something similar to the code below
(note the curly braces around the for loop):

static void Main(string[] args)
{
int foo = 0;

{
for (int j = 0; j < 5; j++)
{
foo += j;
}
}

int j = 5;
}

So basically, what you end up having is the "j" variable on the "for loop"
scooped on level deeper than the "j" variable declared on the main body of
the function. That is why the compiler complains about the variable
interfering with a lower child scope.

If you where to move the "int j = 5;" declaration to the top of the function
you will get a slightly different message that describes the same issue
(parent vs child), this just demonstrates that the compiler tries to resolve
the scoping issue on an orderly fashion.

The bottom line is that thanks to this scoping technique you can do
something like the following (note how "j" is used on both for loops withoug
problems):



static void Main(string[] args)
{
for (int j = 0; j < 5; j++)
{
// Do something here.
}

for (int j = 0; j < 5; j++)
{
// Do something here.
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top