有人可以简单地解释一下,为什么C#中的Lazy需要获得Func?
public Lazy (Func<T> valueFactory);
我知道有时候您需要一个函数来做一些 init()。
但是,很多时候我发现自己写的是单例或简单的东西,只是在创建类的新实例。
如Jon的Skeet书中所示。
http://csharpindepth.com/Articles/General/Singleton.aspx
我觉得这种语法很烦人。
谢谢!
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
答案 0 :(得分:6)
没有初始化函数,您将无法使Lazy
正常工作。这样便可以确保创建对象的逻辑存在但尚未被调用。
考虑一下:
new Lazy<Singleton>(new Singleton());
这已经实例化了一个新的Singleton
。懒惰不再有用。该功能允许Lazy<T>
在将来的任何时候构造对象。
Func<T>
的另一个优点是它不必是实例化的新对象。可以是其他任何东西。它可以是多行语句,可以提取其他内容,等等。
我可以主张的一种优化是{{1}}将在new Lazy<T>()
上使用new()
,这避免了您调用构造函数的需要。但是,使用当前语法是不可能的,但是它可以使用静态工厂方法。
这样的事情(是的,基本上是您现在要做的,但是却藏在了内核中):
T
或如CodeCaster建议的派生类所示:
public static class LazyDefault
{
public static Lazy<TNew> New<TNew>() where TNew : new()
{
return new Lazy<TNew>(() => new TNew());
}
}
答案 1 :(得分:5)
您需要一个功能,因为如果可以的话,
var Lazy<Foo> = new Lazy<Foo>(new Foo());
您已经实例化了您不希望使用的Foo
,否则您不必使用Lazy<T>
开始。
Func<T>
保留着Foo
的初始化程序,但仅在您访问Lazy<T>
的{{1}}时进行初始化。
答案 2 :(得分:1)
您赋予Lazy<T>
构造函数的内容称为 thunk (Wikipedia):
在计算机编程中,thunk是用于注入 额外的计算进入另一个子程序。暴徒主要是 用于将计算延迟到需要计算结果或插入 在另一个子例程的开头或结尾处进行操作。他们有 编译器代码生成中的各种其他应用程序以及 模块化编程。
也就是说,懒惰评估的核心在于,待评估的整个过程都会延迟到真正需要时才进行。
如果您发现必须明确提供Func<T>
而感到烦恼,则可以通过以下方式进行简化:
public static class Lazy
{
public static Lazy<T> Of<T>()
where T : class, new() => new Lazy<T>(() => new T())
}
var lazyFoo = Lazy.Of<Foo>()
答案 3 :(得分:1)
Lazy
需要一个Func
才能真正初始化内部值。使用Lazy的整个目的是仅在需要时才初始化值。因此,应该有一种方法可以在需要时真正地懒惰初始化值,这就是Func
的用处。除了传递初始化函数外,我没有其他实现Lazy
之类的方法。