When to use Lazy<> from C#

Asked

Viewed 197 times

10

Where is a good scenario to use the initializer Lazy<> of the C#?

I ask this because I understand the concept behind the Lazy loading (delay the instance of an object to only when it is necessary), but I have not yet had the need to use, so I would like an example of a good situation of where to implement.

For example, reading the documentation here: Lazy inicialization

There are two examples:

"When you have an Object that is Expensive to create, and the program Might not use it"

or in free translation,

"When you have an object that is costly to be created and may not be used"

In this case, just use a simple if not even create it unless it will use, correct?

"When you have an Object that is Expensive to create, and you want to Defer its Creation until after other Expensive Operations have been completed"

or in free translation

"When you have an object that is costly to be created and want delay its creation until other costly operations have been completed"

I can just change the place where the object was created, do it asynchronously, in another thread, etc, i.e., various ways to circumvent this.

I wanted an example of a situation where actually the Lazy would make a difference, which would resolve whether to have the need for a lot of implementation, or something complex to get around the problem.

2 answers

4


What is not so clear in all of this is that this class should be used whenever the data may or may not be used in the execution of the moment. It’s not just a question of leaving it for later, it’s a question of leaving it for later because who knows it might not even be necessary.

I think it’s clear that it’s only worth doing this if the startup is expensive, so it comes from an expensive operation of a database, or from the internet or service that you have no control over the time spent. It’s kind of the use of async, is only worth it if the operation takes.

In general fields of a structure are initialized at the time of its creation so any situation that it may or may not be used can be useful.

But you have to be careful because people can start using this to make up for design bad. There is situation that what may or may not be used, and therefore delayed, must be part of another object.

Examples

The most common example of using this type is in Orms since the data may or may not be used so it would be better not to ask DB right away. On the other hand, and this is one of the criticisms of the ORM, this can hurt performance because it makes you have more access to the database instead of bringing it all at once. Of course, normally you have it ready and you don’t use the Lazy in your code, unless you’re doing an ORM, and yet you may even prefer a more sophisticated control mechanism, Lazy is quite simple.

I found a example in the OS that shows well that everything that uses the Lazy can do without it:

public sealed class Singleton {
    private static readonly Lazy<Singleton> instanceHolder = new Lazy<Singleton>(() => new Singleton());
    private Singleton() { ... }
    public static Singleton Instance => instanceHolder.Value;
}

And without:

private static object lockingObject = new object();
public static LazySample InstanceCreation() {
    if (lazilyInitObject == null) {
        lock (lockingObject) {
            if (lazilyInitObject == null) lazilyInitObject = new LazySample();
        }
    }
    return lazilyInitObject;
}

I put in the Github for future reference.

I do not know if the example is so good to show the practice (the goal was not this) because the object is only created when it is called once and in this case usually when it calls already needs to be used.

It is the same case of local use (method), you can put in the moment you need. I do not say you should never use, but in general do not need the Lazy. The need for this type has more to do with the fact that you don’t know the exact moment you need. Almost all examples of local use is only to demonstrate the mechanism and not the practice of use.

If you have a static object it can be useful because by specification the initialization of that object can be done at any time from the initialization of the application to the use of that object. The Lazy would be a way to ensure that effective startup occurs only at the time of use.

This is because formal initialization occurs without your control, but what is initialized is object Lazy which is very cheap, and the object that matters (the T) will be initialized when used, The Lazy controls this.

So trying to make a practical use, think that you access the data of a bank teller. In general you only access your account data, but in some cases you can access your account’s transactions, but for some reason the list of these transactions were placed in your account probably to facilitate access and not have an external object.

public Lazy<IList<Transacoes>> trancasoes => new Lazy<IList<Transacoes>>(() => ObtemTranscaoes(this.Id));

I assume that this method takes time to be executed.

Is it a good example? I guess not because it seems to be design bad only, but if you had any reason to keep the transactions close to the account then it makes sense. Most of the examples we find are not even necessary.

An example that can be useful is when there is memoisation. But it can also abuse this and in many cases needs a sophistication that the Lazy does not solve. In others the time he spends is derisory to need lazy boot.

It’s like Pattern design (what this is already ready for use provided by the library), you should know it exists, but not quit applying because it exists. In the rare cases that must be used you have knowledge and will see that there apply, or else that your design is bad and should rethink it.

  • hum I’m still reading everything, but this example of Singleton is very interesting, much cleaner code

  • Manieiro, this gave me an idea: imagine that you have a strategy that creates instances of classes, or a chain of methods, anything like that, and this strategy may take or may never be used, maybe it would be a good application for Lazy in creating the instances, makes sense?

  • I do not know if I understood or if it is clear the details of how this would occur, but an object should have only one strategy. You have several possible strategies, but only one of them would be used (at least looking at one aspect of that object). So there’s no need to create the others, so you don’t have to initialize, it’s not a question of initializing later. Unless you’re talking about that even the chosen strategy may not be used, then it is independent of being a strategy, is the same example I used with this IList, and can be design wrong. And if you’re saying that within the strategy you can have a

  • Lazy for something of it, it has nothing to do with the strategy mechanism, and yes this one in particular may happen to need this.

  • I don’t think I explained it well, I’ll try to put together a code to make it clearer

1

Perhaps a situation that I see that can be very useful and usable is with Func/Delegate, where you can pass a Lazy object that you may or may not use within your Func.

Therefore, within it you could make the appropriate validations to start or not it as well as the manipulation, however, there are other ways to get around this, but this is a very applicable way.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.