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>
就没有意义了,除非你需要一些其他的用途,比如线程安全。