Sunday, August 26, 2007 - 07:07

Problems With Properties

I've always been a bit suspicious of properties in C#. It just seemed a bit dangerous to be actually calling a method when you're seeming to just be setting a value.

Of course it depends what you use properties for. If you're using it purely to, say, check that the user has permission to set that value, it should be fine. But properties are so useful that they tend to be subject to feature creep. Why not set value A at the same time as you set value B? Since A depends on B, it makes sense to set B in the setter for A; that way they will always stay in synch. But now you're introducing side effects that aren't immediately visible when reading the code.

Here's one that bit me the other day: if A should always be rounded to two decimal places, why not do the rounding in the setter? Then you know it will always be rounded. Well, yes - but then you run into this situation:
myPropertyA = someValue;
myPropertyB = someValue;
if (myPropertyA == myPropertyB)
doSomething();
else
doSomethingElse();
And you find that counterintuitively, doSomethingElse always happens instead of doSomething. Whereas this works as you expect:
myPropertyA = someValue;
myPropertyB = myPropertyA;
if (myPropertyA == myPropertyB)
doSomething();
else
doSomethingElse();
Or at least it does if you're not doing anything odd in the setter. It's also easy to give in to feature creep in getters; after all, does it really matter what the real stored value is if you can control what is provided when that value is asked for? Instead of rounding in the setter, for example, you could round in the getter - so the unrounded value is still available by other means, but most code will see the rounded value. The problem is that it's not clear what you're going to get. If I call a method 'GetRoundedValue()', I know I'll get the rounded value. If I use a property, I think I'm getting the stored value but I might really be getting any manipulation of it.

So I tend to keep my property code basic - provide (or deny) access to values, but don't manipulate those values unless you want to have to trace through every step to see what your code is actually doing.

Labels:

0 Comments:

Post a Comment

<< Home