7

From .NET 4 onwards, Lazy<T> can be used to lazily initialize objects. Intuitively, lazy initialization can also be performed in a public property's getter to provide the same functionality to the caller. I wonder if Lazy<T> offers any inherent advantage over the latter and should thus be preferred?

Personally, I feel that Lazy<> can quickly reduce code readability, but perhaps I've just seen it misused. On a plus side, it ensures thread safety, but there are many .NET synchronization constructs that - perhaps I'm wrong - make it quite easy to achieve the same inside a getter.

What are some considerations to be aware of when choosing the best approach?

w128
  • 4,000
  • 6
  • 36
  • 57
  • 1
    Give an example of lazy initialization achieved without `Lazy`. It's not so easy as you seem to think. – Ben Voigt Mar 06 '15 at 15:17
  • 1
    possible duplicate of [Cached property vs Lazy](http://stackoverflow.com/questions/5134786/cached-property-vs-lazyt) – Default Mar 06 '15 at 15:19
  • 1
    Default: missed that one, thanks. This can be marked as a duplicate. @Ben Voigt: similar as to what Patrick Hofman describes in his answer. Besides, I kindly ask people downvoting this to provide comments on how this question could be improved (got to say I'm kind of disappointed by how aggressive this site has become). – w128 Mar 06 '15 at 15:27

1 Answers1

8

Lazy<> can be useful since it inludes support for multithreading too, something you have to build yourself when creating your own 'lazy'.

For code that doesn't need multi-threading, this would be the best performing and readable code in my opinion (using the null-coalescing operator).

return variable ?? (variable = new ClassName());

Note that since this code isn't thread safe, you could end up calling new ClassName() multiple times.

You should introduce locking then, and the readability will decrease. If it is just for readability, Lazy<> might be not that bad in that case.

Also, Lazy<> prevents you to use the backing field in the case of cached properties.

Patrick Hofman
  • 143,714
  • 19
  • 222
  • 294
  • Yes, this is exactly how I would normally proceed to implement lazy loading in a getter - using the null-coalescing operator and some type of locking. To me it doesn't seem any less readable than introducing a bunch of lambda expressions etc., but of course that's subjective and can vary case-by-case. Otherwise, this makes perfect sense - thank you! – w128 Mar 06 '15 at 15:24
  • 2
    @w128 I would never use "some type of locking" instead of using `Lazy`, since `Lazy` already does all that for you. – Matthew Watson Mar 06 '15 at 15:26
  • @MatthewWatson: That was my argument too :) – Patrick Hofman Mar 06 '15 at 15:26
  • @Matthew Watson I'd argue that it depends on a use case. If you're not going to be using multithreading etc. I fail to see how either is different from the other. Of course, if the most general solution is desirable, then this makes sense. – w128 Mar 06 '15 at 15:28
  • @w128 I'm explicitly talking about the case where you need to provide multithreaded safety. In the (perhaps unlikely) case that you don't know if you might need to add multithreaded support later on, then be aware that `Lazy` lets you switch between threadsafe and non-threadsafe very easily. – Matthew Watson Mar 06 '15 at 15:29
  • 3
    @w128 To be clear, I would NOT use Lazy if I didn't need to provide thread safety (unless I thought it was probable that I had to add it some time in the future). – Matthew Watson Mar 06 '15 at 15:33
  • @MatthewWatson thanks; this seems to me to be a good guideline. – w128 Mar 06 '15 at 15:35