Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't C# allow me to use the same variable name in different scopes?

Like for instance:

if ( this.IsValid )
{
    Matrix matrix = new Matrix();
}

Matrix matrix = new Matrix();

The compiler warns me saying:

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

Aren't these variables in different scopes, so I wouldn't be able to access the first matrix from outside the if statement anyway?

like image 834
Joan Venge Avatar asked Jan 10 '11 18:01

Joan Venge


People also ask

Why there is no string in C?

There is no string type in C . You have to use char arrays. By the way your code will not work ,because the size of the array should allow for the whole array to fit in plus one additional zero terminating character.

Why is C not A or B?

Because C comes after B The reason why the language was named “C” by its creator was that it came after B language. Back then, Bell Labs already had a programming language called “B” at their disposal.

What does C++ have that C does not?

C++ was developed by Bjarne Stroustrup in 1979. C does no support polymorphism, encapsulation, and inheritance which means that C does not support object oriented programming. C++ supports polymorphism, encapsulation, and inheritance because it is an object oriented programming language.

Is C very difficult?

It is not hard to learn C. Just like any other skill, you will need patience and resilience to master coding using C. The programming language features 32 keywords for its syntax. This makes it a relatively simple coding language to learn.


2 Answers

UPDATE: The answer below from 2011 is correct for earlier versions of C#; in more recent versions, the rule described the answer has been removed from C#. The design team determined that the rule caused more confusion amongst developers leading to questions like this one than the buggy programs prevented would warrant, even after I greatly improved the error messages to more clearly diagnose the problem.


The answers given so far are very confusing. The correct analysis of the problem starts by reading the error message. The error message is telling you what is actually wrong:

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

Read that carefully. It is telling you precisely which rule of C# is being violated, namely that you are not allowed to use the same name to refer to two different things in the same scope. (Actually, the error message is slightly wrong; it should say "local variable declaration space" where it says "scope", but that is pretty wordy.)

This rule is documented in the C# 4.0 specification, section 7.6.2.1: Simple names, Invariant meaning in blocks.

(It is also illegal to have two local variables of the same name in overlapping declaration spaces. The compiler could be reporting that error as well, but it reports the more general error in this case.)

Aren't these variables in different scopes, so I wouldn't be able to access the first matrix from outside the if statement anyway?

Yes. That statement is true but irrelevant. The error here is that the same simple name has been used to refer to two different things in the same local variable declaration space.

Consider this scenario:

class C 
{
    int x;
    void M()
    {
        x = 10; // means "this.x"
        for(whatever)
        {
            int x = whatever;
        }
    }
 }

Same deal. The error here is that the simple name "x" was used in the outer declaration space to refer to this.x, and was used in the inner declaration space to mean "local variable". Using the same simple name to refer to two different things in the same declaration space -- remember, the inner declaration space is a part of the outer one -- is both confusing and dangerous, and is therefore illegal.

It is confusing for obvious reasons; one has a reasonable expectation that a name will mean the same thing everywhere throughout the declaration space in which it is first used. It is dangerous because small code edits are prone to changing the meaning:

class C 
{
    int x;
    void M()
    {
        int x;
        x = 10; // no longer means "this.x"
        for(whatever)
        {
            x = whatever;
        }
    }
 }

If the declaration spaces in which the simple names are first used are not overlapping then it is legal for the simple names to refer to different things:

class C 
{
    int x;
    void M()
    {
        {
            x = 10; // means "this.x"
        }
        for(whatever)
        {
            int x = whatever; // Legal; now the 
        }
    }
 }

For more information, and an amusing story about fried food, see

http://blogs.msdn.com/b/ericlippert/archive/tags/simple+names/

like image 83
Eric Lippert Avatar answered Sep 28 '22 06:09

Eric Lippert


It is my belief that this is done in order to avoid obscure mistakes or code that's hard to read.

Using the same name of variable between a method scope and a child scope can lead to code that's very hard to read, since the variable type and, worse, meaning, can change and the only hint to the reader will be type declaration keyword before the variable.

However, I can also tell you that the IL generated for methods by the C# compiler will stick all variable declarations at the top, so maybe this decision driver was to simplify the variable parsing tree for the compiler.

In fact, you can find this at MSDN:

The scope of a name is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name. Scopes can be nested, and an inner scope may redeclare the meaning of a name from an outer scope. (This does not, however, remove the restriction imposed by Section 3.3 that within a nested block it is not possible to declare a local variable with the same name as a local variable in an enclosing block.) The name from the outer scope is then said to be hidden in the region of program text covered by the inner scope, and access to the outer name is only possible by qualifying the name.

Emphasis added.

And, from Section 3.3:

Each block or switch-block creates a different declaration space for local variables and constants. Names are introduced into this declaration space through local-variable-declarations and local-constant-declarations. If a block is the body of an instance constructor, method, or operator declaration, or a get or set accessor for an indexer declaration, the parameters declared in such a declaration are members of the block's local variable declaration space. The local variable declaration space of a block includes any nested blocks. Thus, within a nested block it is not possible to declare a local variable with the same name as a local variable in an enclosing block.

Emphasis added.

So, the thing is that while the scopes are different, the variable space is the same.

like image 33
Bruno Brant Avatar answered Sep 28 '22 07:09

Bruno Brant