C#单例模式,使用公共“Instance”字段而不是属性

3
考虑使用类型初始化实现“标准”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() { }
}

我觉得这没问题,但我只看到过第一个被使用,所以我不知道是否有我忽略的错误。

3个回答

9

静态属性有什么意义吗?

有的。它隐藏了从同一类中的字段检索值的实现细节。如果暴露字段,那么你将永远被限制在这个实现上(假设你不能稍后更改/重建所有引用它的代码)。如果使用属性,则可以稍后执行以下操作:

  • 更改为使用 Lazy<T>
  • 在嵌套类中使用字段以获取潜在的更懒惰的初始化,如果您想要在类中具有其他静态方法
  • 使用一些新的花哨方案,但尚未设计

基本上,使用属性,您有未来的选择。使用字段则没有。

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

公共静态只读字段在单例方面工作 - 它只是给你更少的控制权。

作为旁注,您可能希望在您的类中添加一个空的静态构造函数。有关详细信息,请参阅我的文章单例实现beforefieldinit

@SriramSakthivel:请参考 http://csharpindepth.com/Articles/General/Singleton.aspx 中的第5个选项。 - Jon Skeet
谢谢Jon,已经足够了。 - Sriram Sakthivel

0
在单例模式中,使用公共只读字段而不是getter并不会造成太大的危害。
“标准”实现使用getter的原因是为了与其他公共getter保持一致,并使您养成在其他情况下使用getter比公共字段更合适(例如添加功能而不更改接口)的好习惯。

我对“没问题”的部分提出异议 - 它会在以后限制您的选择。请参考我的回答。 - Jon Skeet
1
我想这个问题有两个方面 - 首先是它是否违反了只创建一个实例的原则,其次是即使它在技术上可行,它是否是一个好主意。我认为“没有问题”是指问题的第一部分。 - Stephen Hewlett

-2

Readonly 意味着它是一个实例变量,不能被写入,static 是一个变量,可以在不实例化对象的情况下读取。例如,您可以按以下方式调用它们:

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

//static readonly
var result = singleton.Instance;

你没有理解问题的重点,这是关于暴露属性还是直接暴露字段之间的区别。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接