在.NET 4中,还可以使用System.Lazy<T>
类编写具有缓存属性的以下代码段。我测量了两种方法的性能,它几乎是一样的。对于为什么我应该使用一个而不是另一个,是否有任何真正的好处或魔力?
缓存属性
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;
}
}
}
懒&LT; T&GT;
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; }
}
}
答案 0 :(得分:70)
我一般会使用Lazy<T>
:
请注意,您没有拥有来为委托使用lambda表达式。例如,这是一种可能稍微清洁的方法:
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; }
}
}
当创建过程变得复杂时,这尤其方便。请注意,通过它的外观,您可以在创建代码中使用GradientStops
的集合初始值设定项。
另一种选择是不懒惰,当然......除非你的类中有几个这样的属性,你只想逐个创建相关的对象,你可以在许多情况下依赖懒惰类初始化。
正如DoubleDown的回答所指出的那样,没有办法重置这个以强制重新计算(除非你使Lazy<T>
字段不是只读) - 但我很少发现它很重要。
答案 1 :(得分:7)
使用Lazy<T>
,因为它表达了你正在做的事情 - 延迟加载。
此外,它可以保持您的财产非常干净并且是线程安全的。
答案 2 :(得分:4)
通常,不使用lazy的唯一原因是将变量重置为null,以便下次访问会导致它再次加载。懒惰没有重置,你需要从头开始重新创建懒惰。
答案 3 :(得分:2)
Lazy<T>
将正确地处理并发场景(如果传入正确的LazyThreadSafetyMode ),而您的示例没有任何线程安全检查。
答案 4 :(得分:1)
Lazy<T>
更简单 - 它清楚地表达了代码的意图
它也是线程安全的。
请注意,如果您实际在多个线程上使用此功能,则需要将其设为[ThreadStatic]
; GDI +对象不能跨线程共享。
答案 5 :(得分:0)
Lazy有一些同步化开销来提供线程安全性,而缓存属性在任何其他代码之前通过CLR方式初始化,并且您不需要支付同步成本
从可测试性的角度来看,Lazy是经过充分测试和验证的工件。
但是,在我看来,它比其他选项
有一个非常小的开销答案 6 :(得分:-1)
如果您的性能大致相同,那么在缓存版本上使用Lazy<T>
的唯一原因是,如果您不确定用户是否真的要加载该属性。
Lazy<T>
的要点是等到用户需要资源,然后及时在该实例创建它。如果他们总是需要资源,那么使用Lazy<T>
是没有意义的,除非你需要一些其他目的,比如它是线程安全的。