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

Lazy<T> why does it get Func<T>

谁能简单解释一下,为什么C#中的Lazy需要获取Func?

public Lazy (Func<T> valueFactory);

我知道有时候你需要一个函数来做一些花哨的事情 init().
然而,很多时候我发现自己在写一个单例,或者一些简单的东西,只需要创建一个 class 的新实例。 正如乔恩的双向飞碟书中所示。 http://csharpindepth.com/Articles/General/Singleton.aspx

我觉得这个语法很烦人。

谢谢!

private static readonly Lazy<Singleton> lazy =
        new Lazy<Singleton>(() => new Singleton());

需要一个函数,因为如果您可以这样做:

var Lazy<Foo> = new Lazy<Foo>(new Foo());

您已经实例化了您不想要的 Foo,否则您不必使用 Lazy<T> 开始。

Func<T> 包含 Foo 的初始化器,但仅在您访问 Lazy<T>Value.

时初始化它

如果没有初始化函数,您将无法使 Lazy 工作。这就是它如何确保创建对象的逻辑存在,但尚未调用。

考虑一下:

new Lazy<Singleton>(new Singleton());

这已经实例化了一个新的 Singleton。懒惰的人再也没有用了。该函数允许Lazy<T>在未来的任何时候构造对象。

Func<T> 的另一个优点是它不需要是它实例化的新对象。它可以是任何其他东西。它可以是多行语句、获取其他内容等。

我可以争论的一个优化是 new Lazy<T>() 将在 T 上使用 new(),这样您就不需要调用构造函数。然而,这对于当前语法是不可能的,但它适用于静态工厂方法。

类似这样的事情(是的,它基本上是做你现在做的,但随后隐藏在核心中):

public static class LazyDefault
{
    public static Lazy<TNew> New<TNew>() where TNew : new()
    {
        return new Lazy<TNew>(() => new TNew());
    }
}

或者如 CodeCaster 所建议的派生 class:

public class SuperLazy<T> : Lazy<T>
    where T : new()
{
    public SuperLazy()
         : base(() => new T())
    {
    }
}

你给 Lazy<T> 构造函数的东西被称为 thunk (Wikipedia):

In computer programming, a thunk is a subroutine used to inject an additional calculation into another subroutine. Thunks are primarily used to delay a calculation until its result is needed, or to insert operations at the beginning or end of the other subroutine. They have a variety of other applications in compiler code generation and modular programming.

也就是说,惰性求值的核心是将整个要求值的东西延迟到真正需要的时候。

如果您觉得必须明确提供 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>()

Lazy 需要一个 Func 来实际初始化内部值。使用 Lazy 的全部目的是仅在需要时才初始化一个值。所以应该有一种 Lazy 方法可以在需要时实际初始化值,这就是 Func 的用武之地。除了传递初始化函数之外,我没有看到任何其他方法来实现类似 Lazy 的东西。