【问题标题】:Why the singleton implementation in C# 6.0 does not need the beforefieldinit flag?为什么 C# 6.0 中的单例实现不需要 beforefieldinit 标志?
【发布时间】:2016-07-08 03:34:39
【问题描述】:

我试图理解为什么这是单例模式的正确实现:

public sealed class Singleton : ISingleton
{
    public static Singleton Instance { get; } = new Singleton();

    private Singleton() { }

    // methods
}

beforefieldinit 标志呢?据乔恩斯基特article

只有当类型没有使用名为 beforefieldinit 的特殊标志标记时,.NET 才能保证类型初始值设定项的惰性。不幸的是,C# 编译器(至少在 .NET 1.1 运行时中提供)将所有没有静态构造函数的类型(即看起来像构造函数但标记为静态的块)标记为 beforefieldinit。

最新版C#不需要静态构造函数了吗?

上面的代码是由 Jon Skeet 在 NodaTime 项目中实现的SystemClock。'

编辑 Jon Skeet 代码供参考(为什么我要提到这个 beforefieldinit 标志):

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

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

【问题讨论】:

  • 那个标志呢?我不明白这个问题。
  • @usr 查看编辑:)
  • 显式指定 beforefieldinit 行为存在一个突出的 C# 语言设计问题:github.com/dotnet/roslyn/issues/4448 (fyi)
  • Roslyn online 说该类型被标记为 beforefieldinit:tryroslyn.azurewebsites.net/#f:r/…
  • beforefieldinit 的问题是指实例实例化的惰性,而不是实现是否是正确且安全的单例。您提到的 Jon Skeet 帖子中有一个“性能与懒惰”部分,其中更详细地说明了为什么您可能关心懒惰。

标签: c# singleton


【解决方案1】:

两者都是正确的单例实现。是否需要静态构造函数 just 取决于您对完全惰性的关心程度。如果你真的,真的不希望单例在被调用者使用之前被实例化,你应该有一个静态构造函数——或者使用Lazy<T>。当然,您也可以在 C# 6 代码中使用静态构造函数:

public sealed class Singleton : ISingleton
{
    public static Singleton Instance { get; } = new Singleton();

    static Singleton() { }
    private Singleton() { }

    // methods
}

【讨论】:

  • 现在编译器默认不标记静态构造函数beforefieldinit吧?
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ:我不知道这方面有什么变化,但我会检查一下。
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ:我建议你问一个新的、非常具体的问题。我刚刚确认 C# 编译器仍然添加beforefieldinit,除非有静态构造函数。
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ:当然,我不认为我曾建议它将为空。它只是影响类型初始化器执行的时间。
  • 我尝试了使用和不使用静态构造函数,它似乎与你写的相反?调用静态方法时没有静态ctor不会初始化字段,使用静态ctor总是初始化它们-我刚刚添加了一个返回硬编码字符串的存根静态方法-每当我添加静态ctor时它总是打印控制台写入即使我只调用 Singleton.Stub(),我也已添加到私有 ctor,如果我评论静态 ctor,它不会初始化“实例”并且不会调用私有 ctor(在发布模式 .NET 中测试) 4).
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多