4

Consider the following contrived program:

class Program
{
    static void Main(string[] args)
    {
        var myClass = new MyClass();
        var stuff = myClass.MyProperty; // this takes 5 seconds
        var stuff2 = myClass.MyProperty; // this is effectively instantaneous
    }
}

class MyClass
{
    private Lazy<IEnumerable<string>> _myProperty =
        new Lazy<IEnumerable<string>>(MyService.TimeConsumingLoadOperation);

    public IEnumerable<string> MyProperty
    {
        get { return _myProperty.Value; }
    }
}

class MyService
{
    public static IEnumerable<string> TimeConsumingLoadOperation()
    {
        Thread.Sleep(5000);
        return new List<string>();
    }
}

Drawing from part of CA1024:

Properties should behave as if they are fields; if the method cannot, it should not be changed to a property.

This makes a lot of sense to me. I wouldn't expect that accessing property could result in a noticeable delay, and the code above would be clearer if MyProperty was retrieved in a method call instead. To that end, are there situations where lazy loading a property (as opposed to using a method) would be appropriate?

Will Ray
  • 141
  • 4

1 Answers1

2

Yes, of course lazy loading a property is very often appropriate, since you only suffer the penalty once, while from that moment on retrieving the value of the property is instantaneous.

Someone might argue that it is unacceptable to suffer the loading penalty on the first query without expecting it; the reply to this is that on the contrary, it is unacceptable to suffer the preloading penalty during startup, (at which time we are usually overburdened any way,) by loading the value of a property that we are not even sure whether it will ever be queried.

Things become a bit more complicated if you consider scenarios where the property is not just load-once-query-forever-after, but load-infrequently-query-frequently. How infrequent must the slow loading be to be balanced out by the frequent fast querying before it becomes necessary to advertise the potential slowness of any query by turning the property into a method? This is a question that you have to answer on a case by case basis.

Related: How Much Logic in Getters

Mike Nakis
  • 32,003
  • 7
  • 76
  • 111
  • 1
    What's the drawback of simply using a method then? It communicates more clearly that what is returned is computed. What do you gain by using a property here? – sara May 17 '16 at 14:42
  • Abstraction. What you gain is abstraction. Whether the value of the property is always available, or usually available, (with expensive loading every once in a rare while,) should not be a concern of the caller. If the value of the property is to be *always* loaded, (or otherwise expensively computed,) *then* it should be turned into a function, and the name of the function should contain a verb, such as *calculate*, so as to advertise the expensiveness. – Mike Nakis May 17 '16 at 17:28
  • How is a property (which is really just a (light-weight) method) more abstract than a normal method? There is nothing about methods that say they should be "heavy" or expensive to execute. I'm not saying "don't lazy-load properties", I'm just wondering why it would be better to use a property than a normal method. – sara May 17 '16 at 21:20
  • It is in the culture of C# to always prefer properties over parameterless functions unless you have a good reason to do otherwise. It is the generally accepted and established convention. So, when you see a parameterless function, you always have to wonder "why is this a function and not a property?" And also by convention, the answer is that it being a function advertises that it is expensive. This advertisement is a decrease in abstraction, because it is divulging information about the inner workings of the class. Therefore, it should be avoided unless necessary. – Mike Nakis May 17 '16 at 22:22