Cache vs Lazy <T>

In .NET 4, the next fragment with a cached property can also be written using the System.Lazy<T> class. I measured the performance of both approaches and it is almost the same. Is there any real benefit or magic for why I should use one over the other?

Cached property

 public static class Brushes { private static LinearGradientBrush _myBrush; public static LinearGradientBrush MyBrush { get { if (_myBrush == null) { var linearGradientBrush = new LinearGradientBrush { ...}; linearGradientBrush.GradientStops.Add( ... ); linearGradientBrush.GradientStops.Add( ... ); _myBrush = linearGradientBrush; } return _myBrush; } } } 

Lazy <T>

 public static class Brushes { private static readonly Lazy<LinearGradientBrush> _myBrush = new Lazy<LinearGradientBrush>(() => { var linearGradientBrush = new LinearGradientBrush { ...}; linearGradientBrush.GradientStops.Add( ... ); linearGradientBrush.GradientStops.Add( ... ); return linearGradientBrush; } ); public static LinearGradientBrush MyBrush { get { return _myBrush.Value; } } } 
+48
c # lazy-loading
Feb 27 '11 at 17:47
source share
7 answers

I would use Lazy<T> as a whole:

  • It is thread safe (maybe not a problem in this case, but it will be in others)
  • This makes it obvious what happens only by name
  • It allows null to be a valid value.

Note that you do not need to use the lambda expression for the delegate. For example, here's an approach that might be a little cleaner:

 public static class Brushes { private static readonly Lazy<LinearGradientBrush> _myBrush = new Lazy<LinearGradientBrush>(CreateMyBrush); private static LinearGradientBrush CreateMyBrush() { var linearGradientBrush = new LinearGradientBrush { ...}; linearGradientBrush.GradientStops.Add( ... ); linearGradientBrush.GradientStops.Add( ... ); return linearGradientBrush; } public static LinearGradientBrush MyBrush { get { return _myBrush.Value; } } } 

This is especially convenient when the creation process becomes complicated with loops, etc. Note that in appearance you can use the collection initializer for GradientStops in your creation code.

Another option is not lazy, of course ... if you do not have several such properties in your class, and you only want to create the corresponding objects separately, you can rely on the lazy initialization class for many situations.

As stated in DoubleDown's answer, there is no way to reset this to force redistribution (unless you make the Lazy<T> field not only readable), but I very rarely found this to be important.

+69
Feb 27 2018-11-17T00:
source share

Use Lazy<T> as it accurately expresses what you are doing - lazy loading.

In addition, it keeps your property in a very clean and safe flow.

+7
Feb 27 2018-11-17T00:
source share

Typically, the only reason not to use the lazy one is to reset the variable to null, so the next access forces it to load again. Lazy has no reset, and you will need to recreate the lazy from scratch.

+4
Feb 27 '11 at 18:59
source share

Lazy<T> will correctly port parallel scripts (if you pass the correct LazyThreadSafetyMode ), while your example does not have thread safety checks.

+2
Feb 27 2018-11-17T00:
source share

Lazy<T> simpler, it clearly expresses the intention of the code.
It is also safe for threads.

Please note: if you actually use this for multiple threads, you need to make it [ThreadStatic] ; GDI + objects cannot be shared between threads.

+1
Feb 27 2018-11-17T00:
source share

Lazy has some synchronization overhead to ensure thread safety, while the caching property is initialized with the CLR method before any other code, and you do not need to pay for synchronization costs

In terms of validation, Lazy is well tested and artifact tested.

However, in my opinion, it has very little overhead compared to another option

0
Oct 07 2018-11-11T00:
source share

Well, if your performance is about the same, the only reason to use Lazy<T> over the cached version would be if you are not sure if the user will actually load the property.

The point of Lazy<T> is to wait until the user requires a resource, and then create it in this instance in time. If they always need a resource, then there is no point in using Lazy<T> unless you need some other goals, such as thread safety.

-one
Feb 27 2018-11-17T00:
source share



All Articles