缓存属性vs懒惰
在.NET 4中,还可以使用System.Lazy<T>
类写入以下带有缓存属性的片段。我测量了两种方法的性能,并且几乎相同。对于我为什么应该使用一种优势,有没有什么真正的好处或魔力?缓存属性vs懒惰<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;
}
}
}
懒<牛逼>
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>
:
- 它是线程安全的(可能不是在这种情况下的问题,但会在其他国家)
- 这使得它很明显这是怎么回事只是由命名
- 它允许空值是一个有效的值
请注意,你不有使用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>
字段不是只读) - 但我很少发现这很重要。
在什么情况下会使用懒惰的问题? – user256034 2011-02-27 17:52:34
@ user256034:当你不使用.NET 4时:) – 2011-02-27 17:53:52
谢谢!在你的名单中的3点正是我正在寻找;) – 2011-02-27 18:14:29
的Lazy<T>
简单—它清楚地表达了代码的意图。
它也是线程安全的。
请注意,如果您实际上在多个线程上使用它,则需要将其设置为[ThreadStatic]
; GDI +对象不能在线程间共享。
使用Lazy<T>
,因为它表达了你在做什么 - 懒加载。
此外,它保持你的财产非常干净,线程安全。
那么如果你的性能大致相同,那么在缓存版本上使用Lazy<T>
的唯一原因是,如果你不确定用户是否真的要加载属性。
Lazy<T>
的要点是要等到用户需要该资源,然后在该实例中及时创建它。如果他们总是需要资源,那么使用Lazy<T>
就没有意义,除非你需要其他一些目的,比如它是线程安全的。
-1,OP的替代方案是相同的,即如果该属性永远不会被调用,那么该列表永远不会被实例化。从这个意义上说,他们都是“懒惰”的。 – tsemer 2015-12-31 10:18:37
懒具有一定的同步化开销来提供线程安全的,而缓存的属性由CLR方式在任何其他代码initiliazed,你不需要支付synronization成本
从一个可测试性来看,懒惰已经进行了测试并被证明是神器。
但是,它有一个非常轻微的开销,在我看来,比其他选项
通过使用'懒惰'你是'Lazy'写自己的实现。 (当然,这是一个很好的方法。) –
BoltClock
2011-02-27 17:49:42
有趣的是,我倾向于说它代码少,可读性好,但是你的例子证明情况并非如此。但是,再次,我已经有一个'Property'类来支持支持这个和更常见的后台字段行为的字段。 –
2011-02-27 17:49:58
懒惰允许线程安全 –
Tsayper
2015-08-07 06:29:26