延迟评估的属性语法差异

时间:2019-02-08 07:35:27

标签: c# lazy-evaluation lazy-initialization

对于惰性计算的属性,以下两种方法(具有后备字段的属性和具有默认值的属性)之间是否存在差异?或者它们等效吗?

// (1)
public static class Foo
{
    private static readonly Lazy<Foo> instance = new Lazy<Foo>();
    public static Foo Instance { get; } = instance.Value;
}

// (2)
public static class Foo
{
    public static Foo Instance { get; } = new Lazy<Foo>().Value;
}

我要实现的是,仅在访问Foo时才创建Foo.Instance的实例,而不是之前---如此,当从未访问过Foo.Instance时,则不应该创建任何实例被创造出来。

2 个答案:

答案 0 :(得分:3)

实际上,不,它们没有什么不同。

但是,这只是一个假设,请注意,它们也不起作用,至少不是我希望您希望它们起作用的方式。

您会看到以下语法:

<property declaration> = <expression>;

为该属性声明一个初始化程序,该初始化程序将在拥有类型的构造上执行。

所以这个:

private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance { get; } = instance.Value;

一点也不懒。它会声明并构造一个Lazy<Foo>(尽管即使编译也可能会在这里丢失getter委托),但是,当您声明该属性时,最终会在构造该属性时对惰性对象进行评估拥有类型,因此变得非惰性。

第二个问题完全相同,您构造并立即评估惰性对象,使其变为非惰性。

正确的方法(只能以第一种语法形式实现)是使用没有初始化程序的属性,要么是这样:

private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance
{
    get { return instance.Value; }
}

或者这个:

private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance
{
    get => instance.Value;
}

或者可能是最好的,就像这样:

private static readonly Lazy<Foo> instance = new Lazy<Foo>();
public static Foo Instance => instance.Value;

这将声明一个吸气剂 body ,直到您实际读取该属性后,该吸气剂才会执行。


TL; DR 综上所述,您给出的两个示例并没有什么不同,但是(可能)它们都是错误的,您需要更改属性声明以对其进行修复。

答案 1 :(得分:0)

除了answer给出的出色的Lasse Vågsæther Karlsen之外,我还要进一步推测并假设OP在Singleton实现之后。这是一种完全懒惰的方法。

{{1}}