咨询区
danyolgiax
最近我在看关于 Lazy<T>
的资料,链接:https://sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt , 看是看完了,但我始终想不明白它的应用场景有哪些?
回答区
Matthew
如果你在项目中使用过双检索来实现 单例模式
模式的话,对下面的代码肯定不会陌生。
private static object lockingObject = new object();
public static LazySample InstanceCreation()
{
if(lazilyInitObject == null)
{
lock (lockingObject)
{
if(lazilyInitObject == null)
{
lazilyInitObject = new LazySample ();
}
}
}
return lazilyInitObject ;
}
那现在这种写法已经太low了,完全可以用 Lazy<T>
来替换使用,它是一个线程安全,懒实现的方式,参考如下代码:
public sealed class Singleton
{
// Because Singleton's constructor is private, we must explicitly
// give the Lazy<Singleton> a delegate for creating the Singleton.
private static readonly Lazy<Singleton> instanceHolder =
new Lazy<Singleton>(() => new Singleton());
private Singleton()
{
...
}
public static Singleton Instance
{
get { return instanceHolder.Value; }
}
}
Despertar
Lazy<T>
一个很好的真实示例是使用 ORM(对象关系映射器),例如 Entity Framework 和 NHibernate。
假设您有一个实体 Customer,它具有 Name
、PhoneNumber
和 Orders
属性, Name 和 PhoneNumber 是常规的字符串类型,但 Orders
是一个导航属性,它返回的是 Customer 曾经下过的成百上千的订单。
你可能经常想要查看所有客户的信息并获取他们的 Name
和 Phoneumber
来给他们打电话。这是太普通不过的业务需求了,但想象一下,如果你每次获取客户都把和他相关的上千条订单给拉出来的话,其实这些订单你目前是不需要的,这就是完全的浪费资源!
理想的场景 Order 应该是延迟加载,除非你确实需要它们。
点评区
Lazy<T>
确实非常好用,可以让你更加专注于业务,少写一些累赘代码,但本质上它的底层是用 lock 实现的,参考如下代码:
private void ExecutionAndPublication(LazyHelper executionAndPublication, bool useDefaultConstructor)
{
lock (executionAndPublication)
{
if (_state == executionAndPublication)
{
if (useDefaultConstructor)
{
ViaConstructor();
}
else
{
ViaFactory(LazyThreadSafetyMode.ExecutionAndPublication);
}
}
}
}