Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
675 views
in Technique[技术] by (71.8m points)

scope - C# variable scoping not consistent?

C# is quite nit-picking when it comes to variable scoping. How is it possible that it accepts this code:

class Program
{
    int x = 0;

    void foo()
    {
        int x = 0;
        x = 1;

        Console.WriteLine(x);
    }
}

If you ask me, that's an obvious naming conflict. Still the compiler (VS 2010) accepts it. Why?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The rules for C# name hiding are quite complex. The language allows the case you mention, but disallows many similar cases. See

http://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/

for some information on this complicated subject.

To address your specific question: the compiler certainly could detect that conflict. In fact, it does detect that conflict:

class P
{
    int x;
    void M()
    {
        x = 123; // The author intends "this.x = 123;"
        int x = 0;
    }
}

The equivalent C++ program would be legal C++, because in C++ a local variable comes into scope at the point of its declaration. In C#, a local variable is in scope throughout its entire block, and using it before its declaration is illegal. If you try compiling this program you get:

error CS0844: Cannot use local variable 'x' before it is declared.
The declaration of the local variable hides the field 'P.x'.

See: the local declaration hides the field. The compiler knows it. So why in your case is it not an error to hide a field?

Let's suppose for the sake of argument that it should be an error. Should this also be an error?

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

The field x is a member of D via inheritance from B. So this should also be an error, right?

Now suppose you have this program produced by Foo Corporation:

class B
{
}

and this program produced by Bar Corporation:

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

That compiles. Now suppose Foo Corp updates their base class and ships a new version out to you:

class B
{
    protected int x;
}

You're telling me that every derived class that contains a local variable named x should now fail to compile?

That would be horrid. We have to allow local variables to shadow members.

And if we're going to allow locals to shadow members of base classes, it would seem awfully strange to not allow locals to shadow members of classes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...