简体   繁体   中英

c# What makes the difference between the two this keywords in the constructor below?

I don't understand the following: In the code found below, Visual Studio tells me, that I can simplify my code by deleting the second this keyword in the constructor.

But why can't then I do away with the first this keyword? Both variables were declared outside the constructor, in the class, so both will be "overridden"* for the instance.

If I remove both this keywords, then VS will complain that the first assignment is made to same variable, but not for the second. The only obvious difference to me is the second variable is an array, but I do not understand how would that make it any different?

*I suspect override is not the correct term here.

public class CelestialObject {

    CelestialBody[] celestialBodies;
    int celestialBodyCount;

    public CelestialObject(int celestialBodyCount = 2) {
        this.celestialBodyCount = celestialBodyCount;
        this.celestialBodies = new CelestialBody[celestialBodyCount];
    }
}

You cannot do away with the first this keyword because you have a parameter with the same name as your field celestialBodyCount :

int celestialBodyCount; // The field

And

public CelestialObject(int celestialBodyCount = 2) { // The parameter.

The this keyword is required to indicate that the field is being assigned to. Otherwise the parameter takes precedence over the field, as explained in 3.7.1 Name hiding :

... the scope of an entity may include declarations that introduce new declaration spaces containing entities of the same name. Such declarations cause the original entity to become hidden.

And then 3.7.1.1 Hiding through nesting :

Name hiding through nesting can occur as a result of nesting namespaces or types within namespaces, as a result of nesting types within classes or structs, and as a result of parameter and local variable declarations.

In this case the parameter celestialBodyCount hides the member celestialBodyCount .

Of course, if you do remove the this the compiler will helpfully give you the following warning:

Assignment made to same variable; did you mean to assign something else?

This warning almost always indicates a bug and should always be cleaned up.

The difference is that you've got a parameter called celestialBodyCount - which means that within the constructor, the identifier celestialBodyCount refers to the parameter, so to access the field you have to qualify it with this .

You don't have a parameter (or other local variable) called celestialBodies , so that identifier already refers to the field, without any qualification required.

In this code, without this keyword:

public CelestialObject(int celestialBodyCount = 2) 
{
    celestialBodyCount = celestialBodyCount;
    this.celestialBodies = new CelestialBody[celestialBodyCount];
}

Visual Studio is saying: "I am sorry but without the this keyword there is a celestialBodyCount in the parameter so it will be assigned to itself since it is the closed matching variable with that name. Are you sure this is what you mean? Or do you mean the class level field?" Visual Studio is being friendly to you but the compiler will go ahead and assign celestialBodyCount in the parameter to itself and it will not assign it to your class level field. So be thankful to Visual Studio because the compiler will not remind you.

When you put this.celestialBodyCount then Visual Studio knows knows you are assigning it to the class level field.

For this.celestialBodies , there is no confusion, only one exists so it will work with or without this .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM