延迟评估 属性 语法差异
Lazily evaluated property syntax difference
对于惰性评估 属性,以下两种方法(属性 与支持字段和 属性 与默认值)之间是否存在任何差异,或者它们是否等效?
// (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
从未被访问时,不应该永远创建实例。
嗯,实际上,不,它们并没有什么不同。
但是,请注意,这只是一个假设,它们也没有起作用,至少不是我希望它们起作用的方式。
你看,这个语法:
<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;
这将声明一个 getter body 在您实际阅读 属性.
之前不会执行
TL;DR 综上所述,您给出的两个示例没有什么不同,但它们(可能)都是错误的,您需要更改 属性声明来修复它。
除了优秀 given by Lasse Vågsæther Karlsen,我想进一步推测并假设OP是在Singleton实现之后。这是一个完全懒惰的方法。
Approach 1
public sealed class Singleton {
//Private ctor of course :P
private Singleton() {}
// Instance property to access Singleton Instance
public static Singleton Instance { get { return Nested.instance; } }
private class Nested {
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested() { }
internal static readonly Singleton instance = new Singleton();
}
}
Approach 2
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton()
{
}
}
对于惰性评估 属性,以下两种方法(属性 与支持字段和 属性 与默认值)之间是否存在任何差异,或者它们是否等效?
// (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
从未被访问时,不应该永远创建实例。
嗯,实际上,不,它们并没有什么不同。
但是,请注意,这只是一个假设,它们也没有起作用,至少不是我希望它们起作用的方式。
你看,这个语法:
<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;
这将声明一个 getter body 在您实际阅读 属性.
之前不会执行TL;DR 综上所述,您给出的两个示例没有什么不同,但它们(可能)都是错误的,您需要更改 属性声明来修复它。
除了优秀
Approach 1
public sealed class Singleton {
//Private ctor of course :P
private Singleton() {}
// Instance property to access Singleton Instance
public static Singleton Instance { get { return Nested.instance; } }
private class Nested {
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested() { }
internal static readonly Singleton instance = new Singleton();
}
}
Approach 2
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton()
{
}
}