0

I have two properties in a class that update each other: binary and value, where binary is the binary value and value is the base 10 value. Each updates each other such that when the set method of value is called, binary is updated, and vice versa.

private UInt64 _Binary;
public UInt64 Binary {
    get { return _Binary; }
    set 
    { 
        if (_Binary != value) {
            _Binary = value; 
            BinaryToValue(); 
            UpdateUi(); 
        }
    }
}

private double _Value;
public double Value {
    get { return _Value; }
    set 
    { 
        if (_Value != value) {
            _Value = value;
            ValueToBinary(); 
        }
    }
}

private void ValueToBinary() {
    // Loop through and set each bit high or low as needed
}

If the current Value is a decimal 1 and just the LSB of Binary is set high, then if I change the value to 6, now I am setting 3 bits to different values, meaning the set method of Binary is seeing a different value each time (set bit 0 low (value = 0), set bit 1 high (value = 2), set bit 2 high (value = 4)). In this scenario, BinaryToValue() is also called three times, so the Value property is changing when each of the the three bits is set to a different state, which it should not be because the Value property initially contained the correct value.

How do I prevent this from occurring?

I can't update the backing field because I need the UI to be updated when Binary is modified. I took a look at this question: Properties that update each other, but the solution there does not apply here because I can't update the backing field only.

pavuxun
  • 411
  • 2
  • 15

2 Answers2

3

Correct way would be to only have one serialized and the other one just a getter which performs the conversion as its called (possibly storing a dirty flag and using cached value if performance is a concern). But both should probably not be settable if they represent the same thing in different ways. You could provide methods to set it in both manners, but only use one field to store the value.

If you insist on doing it this way - simply call the UI update after updating the backing field. You cannot have properties update each other as this will cause a loop

Milney
  • 6,253
  • 2
  • 19
  • 33
0

As Milney says (if you really want to do it this way), use just one backing field for both properties:

private UInt64 binary;
public UInt64 Binary { get { return binary; } set { binary = value; UpdateUi(); } }
public double Value { get { return BinaryToValue(); } set { ValueToBinary(value); } }

private double BinaryToValue()
{
    double binaryToValue = 0;
    // logic (convert binary field to double and set it to binaryToValue)
    return binaryToValue;
}


private double lastValue;
private void ValueToBinary(double value)
{
    if (value != lastValue)
    {
        lastValue = value;
        // logic (Binary (the property to activate UpdateUi()) = ...)
    }
}

You can also remove the setter of Value and make it a public method as Milney recommends.

Note: A property's only job should be to get and / or set a backing field's value (validating it's input and notifying about the change if INotifyPropertyChanged interface is implemented), not changing another property value (generating side effects), reinforcing Milney's recommendation of the setter method.