Detecting Property Changes

Detecting Property Changes

My little rant generated some questions that it may be easier to clear up here than 140 characters at a time.

Sometimes you want to execute some functionality when changing the value of a property. The key word there is “changing”. In order to know if the property changed you must compare the new value to the current value. It looks something like this:

// some field in your class
int value;  

void SetValue(int newValue)
{
  if (value != newValue)
  {
    value = newValue;
    // do some stuff that you only want to do if the value changes
  }
}

Works great. I mean, why do extra work if some other code is setting a value to the same value?

But does it work with floating point? I mean, we’re never supposed to do equality comparisons with floating point right? But in this pattern that’s not what we’re really doing is it? We’re just concerned that the value changed. How we arrived at the value being passed in isn’t relevant. This method just cares that the value is different from the previous value.

And this was the source of my frustration in my previous post. I wanted to know that the value had changed, not that it was close. And in my mind at least, using an equality operator is the proper way to do that.

Here is the code behind Unity’s equality operator. Inequality is the same with the opposite sign.

// UnityEngine.Vector3
public static bool operator ==(Vector3 lhs, Vector3 rhs)
{
  return Vector3.SqrMagnitude(lhs - rhs) < 9.99999944E-11f;
}

That works great. It isn’t a bug. It is valuable and even necessary functionality when you’re dealing with floating point and vectors and such. I just believe it doesn’t belong in the operator that’s testing for equality, because close is not the same thing as equals. But maybe that’s just me.

Here is some of the code for the Equals method.

// UnityEngine.Vector3
public override bool Equals(object other)
{
  Vector3 vector = (Vector3)other;
  return this.x.Equals(vector.x) && this.y.Equals(vector.y) && this.z.Equals(vector.z);
}

That is not close, that is equal. And that is what I expect from my equality operators.

This has nothing to do with dealing with floating point rounding errors or the wisdom of comparing calculated floating point values or anything like that. It has to do with expected behavior. But perhaps my expectations are unreasonable and that makes me a clown.

Should Unity change it? Probably not at this point. Who knows what it would break.

And that’s all I have to say about that.

Comments are closed.