Lazy <t>为什么会得到Func <t>

时间:2018-08-21 08:52:25

标签: c# lazy-loading

有人可以简单地解释一下,为什么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());

4 个答案:

答案 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之类的方法。