When to lazy load?

2020-02-26 08:32发布

I lazy load all my members. I have been doing this for a while and simply taken lazy load to be a good thing at face value.

Let's say we have

public class SomeClass
{
   public int anInt;
   public SomeReferenceType member1;

   public SomeClass()
   {
      //initialize members in constructor when needed (lazy load)
      anInt = new int();
      member1 = new SomeReferenceType();
   }
}

Are there any disadvantages to doing things this way? Is this a proper lazy load pattern? Does it make sense to lazy load a value type (with modern RAM does it even matter)?


After what I have learned from your answers, I would like to know if there is any difference between the above and this...

public class SomeClass
    {
       public int anInt;
       public SomeReferenceType member1 = new SomeReferenceType();

       public SomeClass()
       {

       }
    }

8条回答
Evening l夕情丶
2楼-- · 2020-02-26 09:07

A real lazy-loaded property for an int might look something like this:

private int? _heavyLoadedInt;

public int HeavyLoading
{
    get
    {
        if (_heavyLoadedInt == null)
            _heavyLoadedInt = DoHeavyLoading();
        return _heavyLoadedInt.Value;
    }
}

Now if you look at this, you’ll see that there is some overhead here: You have to store the value in a nullable (extra memory); check it for null at every access, and retrieve the value from the nullable at every access.

If your integer really requires some seriously heavy computation, then this construct makes sense. But new int() is not a heavy computation, it just returns 0. The overhead is tiny, but if you add this overhead to an even tinier operation (which is to read an integer), it makes no sense.

查看更多
Deceive 欺骗
3楼-- · 2020-02-26 09:10

Lazy loading is essential when the cost of object creation is very high and the use of the object is vey rare. So, this is the scenario where it's worth implementing lazy loading. The fundamental idea of lazy loading is to load object/data when needed

查看更多
男人必须洒脱
4楼-- · 2020-02-26 09:14

That's not really a lazy load. That's initializing on construction. Typically what we mean in lazy loading is to construct the item the first time it's referenced.

    private string _someField;

    public string SomeField
    {
        get 
        {
            // we'd also want to do synchronization if multi-threading.
            if (_someField == null)
            {
                _someField = new String('-', 1000000);
            }

            return _someField;
        }
    }

It used to be one of the typical ways to Lazy load was a check,lock,check so that you don't lock if it's already created, but since it's possible for two items to pass the check and wait for the lock, you check again in the lock:

public class SomeClass
{
    private string _someField;

    private readonly object _lazyLock = new object();


    public string SomeField
    {
        get 
        {
            // we'd also want to do synchronization if multi-threading.
            if (_someField == null)
            {
                lock (_lazyLock)
                {
                    if (_someField == null)
                    {
                        _someField = new String('-', 1000000);
                    }
                }
            }

            return _someField;
        }
    }
}

There are various ways to do this, in fact in .NET 4.0, there is a Lazy<T> type that can help you do thread-safe lazy-loading easily.

public class SomeClass
{
    private readonly Lazy<string> _someField = new Lazy<string>(() => new string('-', 10000000), true);

    private readonly object _lazyLock = new object();


    public string SomeField
    {
        get
        {
            return _someField.Value;
        }
    }
}

As to the why, typically lazy-loading is a good scheme if the object you are creating tends to be expensive (memory or time) and there's no guarantee you'll need it. If you are reasonably sure it will always be used, then you should just construct it outright.

查看更多
Melony?
5楼-- · 2020-02-26 09:18

Lazy loading is a concept where we delay the loading of the object until the point where we need it. Putting in simple words, on demand object loading rather than loading objects unnecessarily.

For example, consider the below example where we have a simple Customer class and this Customer class has many Order objects inside it. Have a close look at the constructor of the Customer class. When the Customer object is created it also loads the Order object at that moment. So even if we need or do not need the Order object, it’s still loaded.

Link to Example

查看更多
神经病院院长
6楼-- · 2020-02-26 09:18
List<int> number = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        var result = number.Where(x => x % 2 == 0);
        number.Add(20);
        //foreach (int item in result)
        //{
        //    Console.WriteLine("loop1:" + item);
        //}

        foreach (int item in result)
        {
            if (item == 4)
                break;
            Console.WriteLine("loop2:" + item);
        }
        number.Add(40);
        foreach (int item in result)
        {

            Console.WriteLine("loop3:"+item);
        }
        Console.ReadLine();

uncomment first loop and see the difference. very using example to under stand deffred execution and lazy loading.

查看更多
我只想做你的唯一
7楼-- · 2020-02-26 09:20

First of all, initializing a member inside the constructor isn't lazy loading.

Lazy Loading is initializing the member the first time it is requested. A simple example in .NET (with some double-check locking so we don't have threading issues):

public class SomeClass
{
    private object _lockObj = new object();
    private SomeReferenceType _someProperty;

    public SomeReferenceType SomeProperty
    {
        get
        {
            if(_someProperty== null)
            {
                lock(_lockObj)
                {
                    if(_someProperty== null)
                    {
                        _someProperty= new SomeReferenceType();
                    }
                }
            }
            return _someProperty;
        }
        set { _someProperty = value; }
    }
}

Luckily, if you're using .NET 4, you can now user the Lazy<T> Class which handles the issues for you and makes things a lot easier.

Second of all, lazy loading is a good idea when you have many members that could be costly to load and you're sure that you're going to be using all of those values. That cost would cause the type to be un-necessarily slow to instantiate.

Lazy Loading just for the sake of lazy loading is adding unnecessary complexity to your code and could cause issues down the road if done improperly (when dealing with threading, for example).

查看更多
登录 后发表回答