Singleton реализация лень со статическим конструктором

Джон Скит предлагает в своей реализации один сингл, что если вам нужна максимальная лень для вашего синглтона, вы должны добавить статический конструктор, который заставит компилятор маркировать тип как beforefieldinit.

Тем не менее, я провел некоторое тестирование, и кажется, что он более ленив без предварительного поля.

Пример кода (вызов частного конструктора выводится на консоль и проверяется, что поля были инициализированы:

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; } } } 

Когда я вызываю Singleton.Stub (), частный конструктор не ударяется, и когда я раскомментирую статический конструктор, всегда вызывается частный конструктор.

Это единственное отличие, которое я мог отслеживать, созданный статическим конструктором.

В моих попытках понять, какая разница будет в prefieldinit, я также прочитал ответ Skeet в этом сообщении, попробовал его с передачей false для DoSomething () – с или без статического конструктора частный конструктор не вызывается.

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

Когда я вызываю Singleton.Stub (), частный конструктор не ударяется, когда я раскомментирую, что статический ctor private constuctor всегда вызывается.

Неясно, какая ценность здесь, но в принципе у вас есть четыре случая:

  • Статический конструктор, Singleton.Stub называется: инициализатор типа гарантированно запускается
  • Статический конструктор, Singleton.Stub не вызывается: инициализатор типа гарантированно не запускается
  • Нет статического конструктора, Singleton.Stub называется: инициализатор типа может запускаться, но не гарантируется
  • Нет статического конструктора, Singleton.Stub не вызывается: инициализатор типа может запускаться, но не гарантируется

Последние два случая отличаются только тем, что если вы меняете Singleton.Stub на использование статического поля, третий случай становится «инициализатор типа гарантированно работает».