【问题标题】:Should Lazy<T> be preferred to lazy initialization in a getter?Lazy<T> 是否应该优先于 getter 中的延迟初始化?
【发布时间】:2015-05-08 05:36:39
【问题描述】:

从 .NET 4 开始,Lazy&lt;T&gt; 可用于延迟初始化对象。直观地说,延迟初始化也可以在公共属性的 getter 中执行,以向调用者提供相同的功能。我想知道Lazy&lt;T&gt; 是否比后者有任何固有的优势,因此应该被首选?

我个人觉得Lazy&lt;&gt;会很快降低代码的可读性,但也许我只是看到它被滥用了。从好的方面来说,它确保了线程安全,但是有许多 .NET 同步结构——也许我错了——使得在 getter 中实现相同的功能变得相当容易。

在选择最佳方法时需要注意哪些事项?

【问题讨论】:

  • 举一个没有Lazy&lt;T&gt;的惰性初始化例子。这并不像你想象的那么容易。
  • 默认:错过了,谢谢。这可以标记为重复。 @Ben Voigt:类似于帕特里克霍夫曼在他的回答中描述的内容。此外,我恳请投反对票的人向 cmets 提供如何改进这个问题(不得不说我对这个网站变得如此激进感到有点失望)。

标签: c# .net lazy-initialization


【解决方案1】:

Lazy&lt;&gt; 很有用,因为它还包含对多线程的支持,这是您在创建自己的“懒惰”时必须自己构建的东西。

对于不需要多线程的代码,我认为这将是性能和可读性最好的代码(使用 null-coalescing 运算符)。

return variable ?? (variable = new ClassName());

请注意,由于此代码不是线程安全的,您最终可能会多次调用new ClassName()

那你应该引入locking,可读性会降低。如果只是为了可读性,Lazy&lt;&gt; 在这种情况下可能还不错。

此外,Lazy&lt;&gt; 会阻止您在缓存属性的情况下使用支持字段。

【讨论】:

  • 是的,这正是我通常会继续在 getter 中实现延迟加载的方式 - 使用 null-coalescing 运算符和某种类型的锁定。对我来说,它似乎并不比引入一堆 lambda 表达式等更具可读性,但这当然是主观的,并且可能会因情况而异。否则,这很有意义 - 谢谢!
  • @w128 我永远不会使用“某种类型的锁定”而不是使用Lazy&lt;T&gt;,因为Lazy&lt;T&gt; 已经为你做了所有这些。
  • @MatthewWatson:这也是我的论点 :)
  • @Matthew Watson 我认为这取决于用例。如果您不打算使用多线程等。我看不出两者有何不同。当然,如果最通用的解决方案是可取的,那么这是有道理的。
  • @w128 需要明确的是,如果我不需要提供线程安全性,我不会使用 Lazy(除非我认为我可能必须在将来的某个时间添加它)。
【解决方案2】:

对于非多线程目的,您可以使用以下安全 getter:

private Foo? _variable;

public Foo Variable => _variable ?? (_variable = DoSomeHeavyTask()).Value;

【讨论】:

    猜你喜欢
    • 2020-05-10
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多