simple example

T

Tony Johansson

Hello!

Below I have a very simple example that should cause this compile error but
compile fine.
Error 1 A local variable named 'x' cannot be declared in this scope because
it would give a different meaning to 'x', which is already used in a 'parent
or current' scope to denote something else
F:\C#\ConsoleApplication1\ConsoleApplication1\Program.cs 311 14
ConsoleApplication1

Here is how I think.
I have two WriteLine in this main as you can see.
The first one is writing 123 because I use the class name so this is
correct.
The second one is writing 1 but how can the compiler know that I don't want
the class name x instead.

Here is more.
If I change the first WriteLine so I just write x instead of Foo.x I get
this compile error
Error 1 A local variable named 'x' cannot be declared in this scope because
it would give a different meaning to 'x', which is already used in a 'parent
or current' scope to denote something else
F:\C#\ConsoleApplication1\ConsoleApplication1\Program.cs 311 14
ConsoleApplication1

I mean that the compiler wouldn't have the slighest idea which x I refer to
when simply writing x.

Can somebody explain this to me.

class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", Foo.x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}
 
P

Patrice

No you have this error when your declaration is *at the same level* (ie.
inside the same block of code).

Here you just declare a x member belonging to the Foo class.
You declare a local variable x.

The little subtitlity is that :
- if you use the same name at different level, there is no problem (this
your case). You can always access whatever you want using a fully qualified
name (and the compiler uses likely the local variable as it is "nearest")
- if you try to use the same name at the same level, the compiler will choke
as there would be no way to distinguish them even with a full name...
 
T

Tony Johansson

I don't fully understand you.

I mean that when I have this code.
When the first WriteLine is accessing x it access at the class level and
when the second WriteLine as accessing at is at the local level.
So these two are at different levels but why will the comiper give a compile
error then.

class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}

//Tony

Patrice said:
No you have this error when your declaration is *at the same level* (ie.
inside the same block of code).

Here you just declare a x member belonging to the Foo class.
You declare a local variable x.

The little subtitlity is that :
- if you use the same name at different level, there is no problem (this
your case). You can always access whatever you want using a fully
qualified name (and the compiler uses likely the local variable as it is
"nearest")
- if you try to use the same name at the same level, the compiler will
choke as there would be no way to distinguish them even with a full
name...

--
Patrice


Tony Johansson said:
Hello!

Below I have a very simple example that should cause this compile error
but compile fine.
Error 1 A local variable named 'x' cannot be declared in this scope
because it would give a different meaning to 'x', which is already used
in a 'parent or current' scope to denote something else
F:\C#\ConsoleApplication1\ConsoleApplication1\Program.cs 311 14
ConsoleApplication1

Here is how I think.
I have two WriteLine in this main as you can see.
The first one is writing 123 because I use the class name so this is
correct.
The second one is writing 1 but how can the compiler know that I don't
want the class name x instead.

Here is more.
If I change the first WriteLine so I just write x instead of Foo.x I get
this compile error
Error 1 A local variable named 'x' cannot be declared in this scope
because it would give a different meaning to 'x', which is already used
in a 'parent or current' scope to denote something else
F:\C#\ConsoleApplication1\ConsoleApplication1\Program.cs 311 14
ConsoleApplication1

I mean that the compiler wouldn't have the slighest idea which x I refer
to when simply writing x.

Can somebody explain this to me.

class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", Foo.x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}
 
A

Alberto Poblacion

Tony Johansson said:
I mean that the compiler wouldn't have the slighest idea which x I refer
to when simply writing x.

In traditional versions of the C languaje and its derivatives, the
compiler always uses the version of x that is in the most internal scope to
the statement that uses it (for instance, it uses a local x instead of an x
declared as a member variable of the class).

As you have already noted, this can be confusing and can cause errors
when the variable that is being used is not the one that you had in mind
when you wrote the code. For this reason, the designers of C# chose to
forbid this situation, and therefore the compiler does not let you define
inside a scope a variable that has the same name as another variable in an
enclosing scope. This is why you get the error "A local variable named 'x'
cannot be declared in this scope because it would give a different meaning
...."
 
T

Tony Johansson

I think you are wrong because I can for example do it in this way.
This example works. As you can see I have a identifier x declared in both
the local level and at the class level.
I can't fully understand this.

I hope somebody can explain this how it works.

class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", Foo.x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}

//Tony
 
A

Alberto Poblacion

Tony Johansson said:
I think you are wrong because I can for example do it in this way.
This example works. As you can see I have a identifier x declared in both
the local level and at the class level.
I can't fully understand this.

I hope somebody can explain this how it works.

class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", Foo.x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}

Ah, no. This is different because you marked the class variable as
static. If you remove the "static" keyword you will notice that it fails to
compile. The static variable needs to be referred to as "Foo.x" (if you
remove "Foo." you also get a compile error), so the ambiguity is resolved.
 
P

Patrice

This is unrelated with static int x=123.

This is because you declared a local variable x at some point in your code.
But technically speaking a local variable is tied with the current block of
code (or more precisely function) as if all declarations were at the top of
your function.

So using x even before the declaration means that you are trying to use
"x_the_local_variable" (and not only below the point where it is declared as
you perhaps thought). The compiler then tells :
"Cannot use local variable 'x' before it is declared."

With this :
static void Main(string[] args)
{
int x = 1;
{ int x = 1; }
}

You'll get :
A local variable named 'x' cannot be declared in this scope because it would
give a different meaning to 'x', which is already used in a 'parent or
current' scope to denote something else

but is once again unrelated to static int x=123. This is because a local
variable is tied to the current function so even though it is in a inner
block of code, you still have two x local variables named the same way in
this function which is not possible...

An important part from the error message is *local variable* i.e. it is
forbidden because this is another local variable. You are still free to use
the same name for something else (such as a static member) in a parent
scope... I believe this is what could have caused the initial confusion.

So to summarize :
- a local variable is scoped to the current function (even if declared in an
inner block of code inside the function such as a loop) and should be
uniquely named inside this function
- it should be declared before being used (and declaring a variable
somewhere else than at the top of a function is just a conveniance, it
doesn't mean that what is in the current scope changes at this exact point,
technically speaking all local variable declaration are handled as if they
were at the top of the function)
- you are allowed to declare a local variable (so by definition scoped to
the function) and other members tied to other classes with the same name as
you'll always be able to access this last one by using a fully qualified
name...
 
P

Patrice

The OP tells actually that the code compiles fine but was expecting this
compile time error...

This is before this message is for *local variables* (which is what you
described). It doesn't apply to the OP case (i.e. he doesn't try to use two
local variable in the same scope but a local variable and a static member
that has the same name in a parent scope which is allowed).

This is further complicated as it seams the OP thought the location of the
local variable declaration inside the function is meaningfull (i.e. before
the declaration, x would refer to the static member, and after x would refer
to the local variable) when it is not...

I tried to elaborate in another response I just posted...

--
Patrice

"Alberto Poblacion" <[email protected]> a écrit
dans le message de groupe de discussion :
[email protected]...
 
P

Patrice

Foo.x won't compile but if you remove Foo it will compile fine...

There is no ambiguity in having a local variable named x and an instance
member named x (in a non static method you can use this.x if you wan't to
acces the instance member).

IMHO the core problem is that the OP generalized an error message and
thought it applies to all identifiers (when the message is about "local
variables" only).

--
Patrice


"Alberto Poblacion" <[email protected]> a écrit
dans le message de groupe de discussion :
##[email protected]...
Tony Johansson said:
I think you are wrong because I can for example do it in this way.
This example works. As you can see I have a identifier x declared in both
the local level and at the class level.
I can't fully understand this.

I hope somebody can explain this how it works.

class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", Foo.x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}

Ah, no. This is different because you marked the class variable as
static. If you remove the "static" keyword you will notice that it fails
to compile. The static variable needs to be referred to as "Foo.x" (if you
remove "Foo." you also get a compile error), so the ambiguity is resolved.
 
T

Tony Johansson

Hello!

I still don't fully understand why this cause compile error.
I can't understand why not the first WriteLine use the class variable x and
the second will use the local variable x.
I think is very clear and can't understand why the compiler would complain.
class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}


I can understand that this compile fine because you have explicitly stated
that the first WriteLine should use
the class variable x. So when you declared the local variable x this will be
used in the
second writeLine. So this is pretty easy to understand.
class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", Foo.x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}

This example is also easy to understand
static void Main(string[] args)
{
int x = 1;
{ int x = 1; }
}

//Tony
 
P

Patrice

I can't understand why not the first WriteLine use the class variable x
and the second will use the local variable x.

This is because the location of a declaration statement is irrelevant :

"The textual order in which names are declared is generally of no
significance." taken from
http://msdn.microsoft.com/en-us/library/aa691107(VS.71).aspx.

As soon as you declared it somewhere in your function, this local variable x
is just part of your function.

So the line where you use x before the declaration refers to the x local
variable (NOT to the class member). As the declaration needs to be before
the first use, the compiler tells you that you can't use the x local
variable before its declaration...
I think is very clear and can't understand why the compiler would
complain.

Because the first line where x appears is a reference to the x local
variable (and NOT to the class member).
I can understand that this compile fine because you have explicitly stated
that the first WriteLine should use
the class variable x.

This is not what I said :

So :
before the declaration, x would refer to the static member, and after x
would refer
to the local variable : this is what you seems to think

This is NOT the reality (see explanations above).

Just suppress the static int x =123; you'll see that the root error will be
unchanged (the compiler will still complain that you are using the x local
variable before declaring it)...
 
T

Tony Johansson

Hello!

When I compile the code below I get
Error 1 A local variable named 'x' cannot be declared in this scope because
it would give a different meaning to 'x', which is already used in a 'parent
or current' scope to denote something else
F:\C#\ConsoleApplication1\ConsoleApplication1\Program.cs 322 14
ConsoleApplication1

and NOT what you might expect
Error 1 The name 'x' does not exist in the current context
F:\C#\ConsoleApplication1\ConsoleApplication1\Program.cs 321 40
ConsoleApplication1

I mean that for some reason the compiler think that we have a conflict
between these two x variable because of
the compile error.
I think the reason that we get a compile error is because when we have the
second WriteLine that compiler doesn't know if we mean the class variable x
or the local variable x.

class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}


//Tony
 
P

Patrice

class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}

gives (VS 2008) :

Cannot use local variable 'x' before it is declared. The declaration of the
local variable hides the field 'ConsoleApplication1.Foo.x'. (IMO the second
part is not relevant).

Which compiler are you using (it's best to always state the product version
if you are not using the latest available) ? The whole code is :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
class Foo
{
static int x = 123;

static void Main(string[] args)
{
Console.WriteLine("x är {0}", x);
int x = 1;
Console.WriteLine("x är {0}", x);
}
}
}
 
P

Patrice

This is it !

This is what you get up to 2.0 (1.0 not tested ;-))

Rather than this one, with 3.5, you have "Cannot use local variable 'x'
before it is declared. The declaration of the local variable hides the field
'ConsoleApplication1.Foo.x'." which looks much closer to what you expect and
is basically correct...

So it looks messages are improved in the 3.5 compiler. Prior 3.5 I agree
that the error message is totally misleading...

So, it's really best to always mention the version you are using when it is
not current. You may want to upgrade to 3.5 (the compiler is updated but if
you don't use new 3.5 libraires, you can benefit from new language
constructs as the underlying generated IL code still targets the 2.0 CLR).
 

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