Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local variable with same name as instance variable = unexpected results

ASP.NET 4.0 Webforms project. I have the following in my code-behind.

public partial class _Default : System.Web.UI.Page
{
    private string testVar;

    protected override void OnInit(EventArgs e)
    {
        string testVar = "test";
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        var whatsTheValue = testVar;
    }
}

I'm setting a break point inside each method. When the local variable, testVar, is set in OnInit, if I quick watch the instance variable, it also has the value "test". When I play through to Page_Load, the instance variable's value is null.

I ran across this by accident but the behavior is confusing to me. I'm actually surprised that it compiles. I would have expected to see some sort of warning about having two variables with the same name. That being said, it's even more confusing to me that the instance variable picks up the assignment in OnInit, but then immediately loses it when that method is exited.

Can someone explain this behavior to me?

like image 474
Jeremy Wiggins Avatar asked Apr 12 '12 15:04

Jeremy Wiggins


People also ask

What happens if you make a local variable with the same name as an instance variable?

If a local variable and an instance variable have the same name, the local variable shadows or hides the name of the instance variable within the scope of the method.

Is it legal to declare two variables with the same name in the same method in such a way that their scopes overlap?

You cannot declare two variables with the same name in the same scope. is illegal because the scope of both x 's is the Foo class. (Even if one of the x 's were public , or if they had the same type, they would still have the same scope and this would still be illegal).

Is it OK to give the same name to a field and to a local variable of the same class?

Yes you can, but local variable will hide the class variable.

How do you access global variable if there is a local variable with same name in Java?

2) We can access a global variable if we have a local variable with the same name in C++ using Scope resolution operator (::).


1 Answers

BrokenGlass's answer is of course correct; you are not looking at the field in the first place. The local hides the field.

However, I note that no one has addressed this portion of your question:

I'm actually surprised that it compiles. I would have expected to see some sort of warning about having two variables with the same name.

The C# compiler does not issue an error or warning in that case because doing so would create a form of "brittle base class failure". Suppose you have this code:

class B { }

class D : B 
{ 
    void M() 
    { 
        int x;
        ...

where B is made by one team in your organization, and D is made by an entirely different team. Then one day the maintainers of B decides to add a feature that needs a protected field:

class B { protected int x; }

When you recompile D, should it give an error? If it does, then someone on a completely different team just broke your code! C# has been carefully designed to minimize (though not eliminate) this kind of breakage.

Note that C# does give an error if you re-use x to mean two different things in the same code block. For example:

class B { protected int x; }
class D : B 
{ 
    void M() 
    { 
        x = 123; // meaning this.x inherited from B
        if (whatever)
        {
            int x = 10;
            ... 

That's illegal because now in the body of M, the simple name x is used to mean both this.x and local variable x. Because this is potentially confusing and a bad programming practice, we make it an error. However, if you really want that then you can eliminate the error by ensuring that the usages are in *entirely separate blocks:

class B { protected int x; }
class D : B 
{ 
    void M() 
    { 
        {
            x = 123; // meaning this.x inherited from B
        }
        if (whatever)
        {
            int x = 10;

Now the blocks do not overlap and therefore the compiler assumes that you know what you are doing and allows the code to compile.

like image 101
Eric Lippert Avatar answered Jan 04 '23 12:01

Eric Lippert