Thinking about delayed getters on properties in C#6.0 or after that

Here is a typical scenario where one postpones property value creation until the property getter is accessed:

private SomeType something;

public SomeType Something 
{
   get
   {
     if (something == null)
     {
       something = new SomeType();
     }
     return something;
   }
}

This pattern is usually applied when property SomeType is rarely used. It doesn’t make much difference on desktop applications (unless there is a ton of these properties) but it might make some performance gains on mobile apps where performance is more critical and memory is less abundant. Of course, one could use Lazy<T> but that would create an instance of Layz<T> instead plus the instance of SomeType eventually.

Now, there is a Expression bodies on property-like function members proposition for C# 6.0 that allows getter-only properties to be implemented with an expression, i.e.:

public string Name => First + " " + Last;

However, full lambdas aren’t supported thus something field can’t be assigned and we’d end up with a new SomeType instance each time.

So, I was thinking a bit about how that could be implemented and here is my proposition for delayed getter-only property assignment:

public SomeType Something => const new SomeType();

This would cause the instance of SomeType to be created only when getter is first time accessed and after that the same instance would be used just like in the original example.

What do you think?

Comments (7) -

  • Joseph N. Musser II

    3.10.2014 16:19:40 | Reply

    I like it. I don't like 'const' though, 'const' and 'readonly' give the sense that the backing field does not change, lazily or otherwise. If I saw 'const' or 'readonly' I would assume that it was done as class initialization.

    Propose a new keyword, 'lazy'. It does exactly what it sounds like. Context is easy, if you only use it at the beginning of an expression body. Plus: where else could use use the keyword 'lazy' if you could? Local declaration/instantiation statements?

    • Miha Markic

      22.10.2014 8:05:57 | Reply

      Yeah, ideally lazy or delayed would be fine. But the language team really doesn't like adding new keywords unless really necessary. Thus the reuse of "best fit".

  • Daniel Rose

    6.10.2014 15:27:53 | Reply

    Is there such a big disadvantage in using Lazy<T>? Yes, there is an additional object. On the other hand, it is thread-safe (and allows specifying how that should be achieved), while your code is not thread-safe.

    • Miha Markic

      11.10.2014 17:03:39 | Reply

      Hi Daniel,

      You are correct. the thing is that you would really want to minimize memory usage on mobile devices. Note that it is not just memory, there is also garbage collection. So, it such properties are rarely accessed it makes sense not to create anything if possible. It is just an optimization.
      You are right on thread safety point as well. The thing is that often thread safety can be ignored (not a general rule, it depends) either because the properties are accessed by same thread (i.e. UI one) and aren't thread safe or because it is not important if two or more instances are created at same time (if that's a very small chance and it doesn't ruin the program flow).

  • jernejgoricki

    1.1.2015 22:56:51 | Reply

    I have just discovered LazyInitializer Class and I remembered this blog post and the debate on twitter. If you want to minimize memory usage and be thread-safe you can apparently write something like this:

            private SomeType _something;
            public SomeType Something
            {
                get
                {
                    return LazyInitializer.EnsureInitialized(ref _something);
                }
            }

    This method is overloaded a couple of times and this example shows the simplest version where an instance of SomeType is created  from the default constructor using Activator.CreateInstance but you can also provide your own value factory, synchronization object and even an boolean value if the type can legitimately be null at some point after it was already initialized.

Pingbacks and trackbacks (2)+

Loading