caching属性vs Lazy <T>

在.NET 4中,还可以使用System.Lazy<T>类写入以下带有caching属性的片段。 我测量了两种方法的性能,这几乎是一样的。 对于为什么我应该使用一个,有没有真正的好处或魔力?

caching属性

 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; } } } 

懒惰<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; } } } 

一般来说,我会使用Lazy<T>

  • 这是线程安全的(在这种情况下可能不是问题,但会在其他情况下)
  • 这就明显地说明了这个名字是怎么回事
  • 它允许null是一个有效的值

请注意,您不必为委托使用lambdaexpression式。 例如,这里有一个可能稍微更清洁的方法:

 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; } } } 

当创build过程变得复杂并带有循环等时,这一点特别方便。请注意,通过外观,您可以在创build代码中使用GradientStops的集合初始值设定项。

当然,另一个select是不要懒惰地执行这个操作,除非你的类有几个这样的属性,而且你只想一个一个地创build相关的对象,那么你可以依赖懒类的初始化的情况。

正如在DoubleDown的答案中指出的,没有办法重置这个来强制重新计算(除非你让Lazy<T>字段不是只读),但是我很less发现这很重要。

使用Lazy<T> ,因为它expression了你在做什么 – 懒加载。

此外,它保持你的财产非常干净,是线程安全的。

通常,不使用懒惰的唯一原因是将该variables重置为空,以便下一次访问使其重新加载。 懒惰没有重置,你需要重新从头开始懒惰。

Lazy<T>将正确处理并发场景(如果传入正确的LazyThreadSafetyMode ),而您的示例没有任何线程安全检查。

Lazy<T>更简单 – 它清楚地expression了代码的意图。
这也是线程安全的。

请注意,如果你真的在多个线程上使用它,你需要使它[ThreadStatic] ; GDI +对象不能在线程之间共享。

懒惰有一些同步开销提供线程安全,而caching的属性启动CLR方式之前任何其他代码,你不需要支付synronization费用

从可testing性的angular度来看,懒惰是经过充分testing和certificate的神器。

但是,在我看来,它的开销很小,而不是其他的select

那么如果你的性能大致相同,那么在caching版本上使用Lazy<T>的唯一原因是,如果你不确定用户是否真的要加载属性。

Lazy<T>的要点是要等到用户需要资源,然后及时创build它。 如果他们总是需要资源,那么使用Lazy<T>就没有意义了,除非你需要一些其他的用途,比如线程安全。