C#Singleton with public';实例';字段而不是属性

本文关键字:属性 字段 with C#Singleton 实例 public | 更新日期: 2023-09-27 18:28:40

考虑带有类型初始化的单例模式的"标准"C#实现:

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();
    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
    private Singleton() { }
}

静态属性有意义吗?如果静态字段被标记为只读,那么它肯定不能从任何地方写入,包括从类外写入。对于更简洁的实现,这是否可行?:

public sealed class Singleton
{
    public static readonly Singleton Instance = new Singleton();
    private Singleton() { }
}

这对我来说似乎很好,但我只见过最上面的一个,所以我想知道我是否错过了什么。

C#Singleton with public';实例';字段而不是属性

静态属性有意义吗?

是的。它隐藏了从完全相同的类中的字段检索值的实现细节。如果您公开了该字段,那么您将永远使用该实现(假设您以后无法更改/重新生成所有引用它的代码)。如果你使用一处房产,你可以稍后使用:

  • 更改为使用Lazy<T>
  • 如果您希望类中有其他静态方法,请使用嵌套类中的字段来获得可能更延迟的初始化
  • 使用一些尚待设计的新颖方案

基本上,有了一处房产,你就有了未来改变的选择。有了田地,你就没有了。

我过去并不认为这是一个相关的区别,但在Noda Time中,我遇到过复杂的类型初始化排序问题,这使得我能够控制这类事情变得非常重要。我在早期版本中公开了一个公共静态只读字段,后来我后悔了:(

公共静态只读字段的工作原理是仍然是一个单例——它只会给你更少的控制。

顺便说一句,可能希望在类中添加一个空的静态构造函数。有关更多详细信息,请参阅我关于singleton实现和beforefieldinit的文章。

在Singleton模式的情况下,拥有一个公共只读字段而不仅仅是一个getter并不是很有害。

"标准"实现使用getter的原因是与其他公共getter保持一致,并使您在getter比poublic字段更合适的所有其他情况下养成良好的习惯(例如,在不更改接口的情况下添加功能)

Readonly意味着它是一个无法写入的实例变量,static是一个可以在不实例化对象的情况下读取的变量。例如,您可以这样称呼它们:

//Readonly
var readonlySingleton = new singleton();
var result = readnlySingleton.Instance;
//static readonly
var result = singleton.Instance;