tags:

views:

459

answers:

4

When should I use a readonly property as opposed to a parameterless method?

+4  A: 

My rule of thumb is that if the action of retrieving a value has side effects, or if you're retrieving a new instance of something each time, then use a method. If you're essentially retrieving a value that doesn't change and doesn't affect other parts of the class, read-only properties are the way to go.

Matt Hamilton
A: 

Nomenclature; when you want to use the name directly, as opposed to with decoration. While this seems trivial and simple, in practice, it can make for considerably more readable code. As Matt says, though, there's some validity to making the decision based on the simplicity of the operation being performed. I tend to take a slightly more complex view; I think that a property should be able to do non-trivial things, but it should be relatively simple and deterministic nonetheless, to avoid confusion. It's easy to access a property thinking that it's just an accessor; and if your property engages in complex or non-deterministic behavior, that can be confusing.

McWafflestix
+10  A: 

Essentially it comes down to the expense of querying the value, and whether you would like the user to cache the returned value.

If you have a property, you're implicitly saying this type of code is OK, where the caller repeatedly accesses the property:

DoSomething(myObj.MyVal);
DoSomethingElse(myObj.MyVal);
DoEvenMore(myObj.MyVal);

However if you have a method then you're saying that there is some cost to calling this method, and so if you are going to use it repeatedly then you should retrieve the value once and re-use it:

var myVal = myObj.GetMyVal();
DoSomething(myVal);
DoSomethingElse(myVal);
DoEvenMore(myVal);

So if the value is cheap to query (e.g. just accessing a backing field) then use a property, but if it takes more effort and you have to compute stuff or look up a lot of info each time, then use a method.

Greg Beech
+2  A: 

Expanding on @Greg Beech's answer:

Methods are usually verbs, and their nature implies side-effects and/or computation.

Properties on the other hand are just properties. Things we want to query the object about.

While a method can imply the caller should cache the value, the class could just as easily be lazy-load and hide cost of repeated queries on the value. The unmentioned assumption is that the value isn't expected to change between invocations of a property.

So the subtlety is really around state-altering and/or side-effects. A property should be side-effect free and get()'ing shouldn't change its own state, nor should its state change between repeated invocations. That's not to say that a change to property X doesn't affect property Y, but repeated get() calls to X or Y should be invariant.

A method invocation implies either side-effects or a volatile result - i.e. the results may change on subsequent invocations.

class Account
{
    decimal Balance { get; private set; } // a simple property
    AccountHolder { // a lazy-load property
        get {
            if( accountHolder == null )
            {
                accountHolder = Repository.GetAccountHolder(ID); // whatever
            }
            return accountHolder;
        }
    }
    // this may change between subsequent invocations. not cached
    IEnumerable<Transaction> GetOverdrawnTransactions()
    { 
        foreach( Transaction t in Repository.GetCurrentTransactions(this)) // whatever
        {
            if( t.IsOverdrawn )
                yield return t;
        }
        yield break;
    }
    // this is state-altering.
    decimal UpdateBalance()
    {
        Balance += 1.5m;
        return Balance;
    }
}
Robert Paulson