What advantages does Lazy<T> offer over standard lazy instantiation?
Asked Answered
I

1

14

Consider this example, it shows two possible ways of lazy initialization. Except for being thread-safe, are there any specific advantates of using Lazy<T> here?

class Customer {
    private decimal? _balance2;
    private static decimal GetBalanceOverNetwork() {
        //lengthy network operations
        Thread.Sleep(2000);
        return 99.9M;
    }

    public decimal? GetBalance2Lazily() {
        return _balance2 ?? (_balance2 = GetBalanceOverNetwork());
    }

    private readonly Lazy<decimal> _balance1 = new Lazy<decimal>(GetBalanceOverNetwork);

    public Lazy<decimal> Balance1 {
        get { return _balance1; }
    }
}

UPDATE:

Please consider above code as a simple example, data types are irrelevant, the point here is to compare Lazy <T> over standard lazy initialization.

Install answered 25/7, 2011 at 7:44 Comment(7)
Given that _balance1 is already readonly, and the accessor doesn't do anything besides return the value, what are you gaining from using a property?Bronk
@Karl, initialization without private set and constructor, no?Gain
@Karl, probably nothing, except another way to confuse my fellow developers.Install
Shouldn't GetBalance2Lazily() and Balance1 return a decimal, not decimal? or Lazy<decimal>?Lyceum
I used nullable decimal to use this nify null coalescing operator (??). I could easily use decimal type, but that would require more keystrokes.Install
Interesting that Lazy<T> does not have an implicit (or explicit) conversion to T.Thelen
Why do you expose the Lazy<T> in your public property? I would have return its value. And why is your first public property Decimal?? That the private fields are of these types is understandable. But leaking details about your lazy initialization into the public API is probably not a wise choice.Oxalis
H
6

It is semantically more correct.

When you use the Nullable<decimal>, what you say is that the value of null will stand for the "unevaluated" state. Although this is a common conversion, it is still arbitrary. There are million other ways to interpret null, so you should probably explain somewhere (in the documentation or at least as a comment) what null means in this case.

On the contrary, when you use Lazy<decimal>, your intentions are clear.

Helaina answered 25/7, 2011 at 8:2 Comment(2)
Fascinating! I should have thought of this. I often use the colourful term "brain damage" to refer to the inability to see what's more or less semantically correct and/or intuitive, as a result of having been forced by more primitive languages to do things in a more round-about way. It's always a shock to discover that one's own brain has been damaged :)Bronk
I have to take issue with this answer, as it is based on an incorrect assumption in the example code. GetBalance2Lazily() does not have to return a nullable because it will never return null. It should instead be written as public decimal GetBalance2Lazily() => _balance2 ?? (_balance2 = GetBalanceOverNetwork()); (which could also be written as a property, not a function) and since it's not nullable, there's no semantic to explain to a consumer. As such, this answer technically doesn't address the intent of the original question, at least as titled, and that's what I'm after.Martino

© 2022 - 2024 — McMap. All rights reserved.