简体   繁体   中英

Property name in getter/setter

I am creating some properties and came across a scenario I haven't seen before.

Consider

private double _temperature;
private double _maxTemp;

public double Temperature
{
    get { return _temperature; }
    set { _temperature = value; }
}
public double MaxTemp
{
    get { return _maxTemp; }
    set { _maxTemp = value; }
}
public bool IsTempToHigh
{
    get
    {
        if (_temperature < _maxTemp)
            return true;
        else
            return false;
    }
}

No problem here but I have a lot of properties in this fashion and I rewrote it into this:

public double Temperature { get; set; }
public double MaxTemp { get; set; }
public bool IsTempToHigh
{
    get
    {
        if (Temperature < MaxTemp)
            return true;
        else
            return false;
    }
}

Quite a bit cleaner in my opinion and it seems to works just as fine. However, I nerver seen or noticed anyone using the property names directly in gettes (or setters), so is it safe to use or might there be any pitfalls.

Also why does this compile but gives an StackOverflowException:

public double Value
{
    get { return Value; }
    set { Value = value; }
}

If you mean in terms of IsTempTooHigh , that's fine (although the condition is the wrong way round for the name). It's entirely valid to refer to one property within another, although you need to be careful that you don't make it recursive. Your autoimplemented properties still have backing fields - they've just been generated by the compiler for you rather than being present in your source code.

I'd rewrite your computed property without the if , mind you:

public bool IsTempTooHigh { get { return Temperature >= MaxTemp; } }

Or in C# 6:

public bool IsTempTooHigh => Temperature >= MaxTemp;

As for the stack overflow, it's simplest to imagine they were methods instead:

public double GetValue()
{
    return GetValue();
}

public void SetValue(double value)
{
    SetValue(value);
}

Can you see why calling either of those would cause a stack overflow? Well, it's just the same for properties - they're just methods with a bit of metadata linking them, basically.

First question: Yes your change makes the code clearer in my opinion. A valid case for using backing fields is if you want immutability. The fields are then readonly and you have no setters.

Second question: Your setter calls your setter. Which calls your setter. Which calls your setter. And so on. After a while the stack becomes too large and you get the error. :)

You can easily use other properties, fields and methods inside your properties. No worries at all.

Your second code block however, calls the same property over and over again. You are trying to mix auto-implemented properties with hand-written properties. That is not possible.

Or the compiler generates backing fields for you (when you use auto-implemented properties) or you have to create them yourself (hand-written properties).

So it is either this:

public double Value { get; set; }

Or:

private double _value;
public double Value
{
    get { return _value; }
    set { _value = value; }
}
  1. It's safe and fine to use property names in private member functions where you currently use the data members.

  2. That code throws a StackOverFlow exception because by assigning to Value you're actually calling the property. Instead, change the name of the underlying data member to be _value :

     public double Value { get { return _value; } set { _value = value; } } 

It is fine to have a property that evaluates 2 other properties. Of course you easily use a method to do the same job. Eg change

public bool IsTempToHigh
{
    get
    {
        if (_temperature < _maxTemp)
            return true;
        else
            return false;
    }
}

to

public bool IsTempToHigh()
{
    return _temperature > _maxTemp;
}

(note: I have changed your < to > assuming this to be correct)

You get an exception on your value because you are set the object itself. This then changes it's value, so it tries to set itself again....

so this is wrong...

public double Value
{
    get { return Value; }
    set { Value = value; }
}

but either of the following would be ok

public double Value { get; set;}

or

private double _myVal;

public double MyValue
{
    get{ return _myVal;}
    set{ _myVal = value;}

}

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