C# – What’s the best way to handle updates only when a value has changed

c

I have an application that receives a number of values that need to be applied to various properties of an object (sealed class). Originally I just set the value without checking anything and updated the object, but of course sometimes the new values wouldn't be valid, and other times they would be identical to existing values, so running an update was a waste of system resources, and frankly a rather slow process.

To get around this, I've created a private bool that is set to true if/when a new value is applied, which is determined with a method that checks if the value is different (and valid):

private bool updated = false;
private bool updateValue(string property, string value, bool allowNulls = false)
{
    if ((allowNulls || !string.IsNullOrEmpty(value)) && !property.Equals(value)) { updated = true;  return true; }
    return false;
}

Then, whenever I need to set the value of a property to something new, I have a single If Statement:

if (updateValue(obj.property, newValue))
{ obj.property = newValue; }

And then of course, when all properties have been assigned their new values:

if (updated)
{ obj.commitChanges(); }

So, 1) Is there a better way of doing this, and 2) is there a more concise way to run my If statement? Single-line If clauses like this annoy me; it seems like I should be able to say "Set A to B when C".

Best Answer

No.

No.

All the no!

Firstly, don't make your callers do all that work! When I want to set a value, I just want to set it! And you're working in a language that makes it easy to write setters and getters. Use them.

Here's what your callers should write:

obj.propA = valueA;
obj.propB = valueB;

And come time to persist obj, if you're doing something active record style, it's just this:

obj.Save();

Your setters need to throw exceptions if you supply a bad value.

Secondly, don't make your callers care what Save() or commit() does or doesn't do. The persistence method itself needs to check dirty flags or compare hashes or serializations to determine whether it actually does work.

Any really, whatever strategy you choose is probably totally fine. Really! Compare the lines of code, performance implications, and semantic "feeling" of each, and pick the one that feels right.

Heck, what's "right" might even vary between classes or projects.

Either way, don't make your callers care about it.