静态构造函数的单例实现懒惰 [英] Singleton implementation laziness with static constructor

查看:81
本文介绍了静态构造函数的单例实现懒惰的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Jon Skeet建议在他的单例实施中 ,如果您需要最大程度的懒惰您的单个,您应该添加一个静态构造函数,这将使编译器将类型标记为beforefieldinit./p>

但是,我进行了一些测试,似乎在没有 beforefieldinit的情况下,它更加懒惰.

代码示例(私有构造函数将输出调用到控制台并验证字段是否已初始化:

 公共密封类Singleton{私有静态只读Singleton实例= new Singleton();公共静态字符串Stub(){返回"123";}//明确的静态构造函数告诉C#编译器//不将类型标记为beforefieldinit//静态Singleton()//{//}私人Singleton(){Console.WriteLine("private ctor");}公共静态单例实例{得到{返回实例;}}} 

当我调用Singleton.Stub()时,私有构造函数没有被击中,而当我取消注释静态构造函数时,总是调用私有构造函数.

这是我可以跟踪的由静态构造函数产生的唯一差异.

在试图了解beforefieldinit有什么区别的同时,我也阅读了Skeet的答案这篇文章尝试通过将false传递给DoSomething()来进行尝试-无论是否带有静态构造函数,都不会调用私有构造函数.

  public static void DoSomething(布尔式){如果(哪个){var a = Singleton.Stub();}别的{Faketon.Stub();}} 

解决方案

当我调用Singleton.Stub()时,私有构造函数没有被使用,而当我取消注释时,总是调用静态ctor私有构造函数.

目前尚不清楚哪个的值在哪里,但是从根本上讲,您有四种情况:

  • 静态构造函数, Singleton.Stub 称为:确保类型初始化程序可以运行
  • 静态构造函数, Singleton.Stub 未调用:保证类型初始化器不运行
  • 没有静态构造函数,称为 Singleton.Stub :类型初始化程序可以运行,但不能保证
  • 没有静态构造函数,没有调用 Singleton.Stub :类型初始化程序可以运行,但不能保证

最后两种情况的区别仅在于,如果将 Singleton.Stub 更改为使用静态字段,则第三种情况将变为保证类型初始化程序可以运行".

Jon Skeet suggests in his singleton implementation that if you require the maximum laziness for your singleton you should add a static constructor which will make the compiler mark the type as beforefieldinit.

However, I did some testing and it seems that it's more lazy without the beforefieldinit.

Code sample (the private constructor call outputs to console and verifies that the fields were initialized:

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

    public static string Stub()
    {
        return "123";
    }

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    //static Singleton()
    //{
    //}
    private Singleton()
    {
        Console.WriteLine("private ctor");
    }

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

When I call Singleton.Stub() the private constructor is not being hit, and when I uncomment the static constructor, the private constructor is always called.

This is the only difference I could track made by the static constructor.

In my attempts to understand what difference will the beforefieldinit do I've also read Skeet's answer in this post tried it with passing false to DoSomething() - with or without the static constructor the private constructor is not being called.

public static void DoSomething(bool which)
{
    if (which)
    {
        var a = Singleton.Stub();
    }
    else
    {
        Faketon.Stub();
    }
}

解决方案

When I call Singleton.Stub() the private constructor is not being hit, when I uncomment the static ctor private constuctor is always called.

It's not clear what the value of which is here, but fundamentally you've got four cases:

  • Static constructor, Singleton.Stub called: type initializer is guaranteed to run
  • Static constructor, Singleton.Stub not called: type initializer is guaranteed not to run
  • No static constructor, Singleton.Stub called: type initializer may run, but isn't guaranteed to
  • No static constructor, Singleton.Stub not called: type initializer may run, but isn't guaranteed to

The last two cases only differ in that if you change Singleton.Stub to use a static field, the third case becomes "type initializer is guaranteed to run".

这篇关于静态构造函数的单例实现懒惰的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆