Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cached property vs Lazy<T>

In .NET 4 the following snippet with a cached property can also be written using the System.Lazy<T> class. I measured the performance of both approaches and it's pretty much 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; }     } } 
like image 634
Martin Buberl Avatar asked Feb 27 '11 17:02

Martin Buberl


People also ask

What is Lazy T?

This enables the Lazy<T> object to create a copy of the lazily initialized object on each of several threads if the threads call the Value property simultaneously. The Lazy<T> object ensures that all threads use the same instance of the lazily initialized object and discards the instances that are not used.

Is Lazy T thread safe?

By default, Lazy<T> objects are thread-safe. That is, if the constructor does not specify the kind of thread safety, the Lazy<T> objects it creates are thread-safe.

Should I use Lazy C#?

Use lazy initialization to defer the creation of a large or resource-intensive object, or the execution of a resource-intensive task, particularly when such creation or execution might not occur during the lifetime of the program.

Are properties cached Python?

cached_property is a decorator that converts a class method into a property whose value is calculated once and then cached like a regular attribute. The cached value will be available until the object or the instance of the class is destroyed.


1 Answers

I would use Lazy<T> in general:

  • It's thread-safe (may not be an issue in this case, but would be in others)
  • It makes it obvious what's going on just by the name
  • It allows null to be a valid value

Note that you don't have to use a lambda expression for the delegate. For example, here's an approach which may be slightly 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 particularly handy when the creation process gets complicated with loops etc. Note that by the looks of it, you could use a collection initializer for GradientStops in your creation code.

Another option is not to do this lazily, of course... unless you have several such properties in your class and you only want to create the relevant objects on a one-by-one basis, you could rely on lazy class initialization for many situations.

As noted in DoubleDown's answer, there's no way of resetting this to force recomputation (unless you make the Lazy<T> field not readonly) - but I've very rarely found that to be important.

like image 197
Jon Skeet Avatar answered Sep 19 '22 09:09

Jon Skeet