Sunday, 18 November 2012

Scope of Local Variables in C# and C++

Consider the following code in C++:


This code actually compile and the output is the following:


The important thing to notice here is that in C++ is possible to declare a variable with the same name in a nested block.

In fact the standard documentation say:

"A name declared in a block is local to that block; it has block scope. Its potential scope begins at its point of declaration and ends at the end of its block. A variable declared at block scope is a local variable."

In C# this is not possible. The following code does not compile:

In C# you cannot declare another local variable with the same name in the current block or in any nested blocks. In addition, the variable scope extends in both directions throughout its code block. 

Even the following code does not compile:


I would say that the restriction imposed by C# is good and avoid unexpected behaviours in some situations. It also encourages to use meaningful names for variables avoiding to reuse the same variable for different purposes.

However, the following C# code compiles:


This because the two blocks are not related to each others. They are not part of the same chain of nested blocks. This is good because there is a typical situation when you like to reuse the same variable name in loops. 

This code compiles:


2 comments:

  1. C++ seems more logical and consistent given that C# does allow a method variable to shadow a class field but I think that the C# behaviour is preferable for avoiding mistakes. I've hit a few bugs where class fields were accidentally redeclared in methods so I would like the compiler to prevent that too.

    e.g.
    class MyClass
    {
    int m_X = 10;
    public void Load()
    {
    int m_X = 20; // mistake, shadowed this.m_X!
    }
    public void Print()
    {
    Console.WriteLine(m_X);
    }
    }

    ReplyDelete
  2. C++ is consistent because simply allows everything. It always assume you know what you are doing. It is by design :)

    What you say about shadowing a class field is true. C# is permissive in some situations.

    I tried to change a little bit your code with this:

    class MyClass
    {
    int x = 10;

    public void Load()
    {
    x = 10;
    int x = 0;
    }

    public void Print()
    {
    Console.WriteLine(x);
    }
    }

    This code does not compile!!! :)

    You get the following error:

    Error 1 Cannot use local variable 'x' before it is declared. The declaration of the local variable hides the field 'ConsoleApplication.MyClass.x'.

    Anyway, ReSharper detects this and nobody stop you to set severity to "Error".

    This is one of the reason why some people like using underscores before the name of a field. However, I honestly don't like it. I use "this" only in constructors and generally I tend to avoid to use local variables with the same name of fields.

    Thanks for you comment. Very interesting

    ReplyDelete

What you think about this post? I really appreciate your constructive feedback (positive and negative) and I am looking forward to start a discussion with you on this topic.