2016-05-24 3 views
4

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

Тем не менее, я сделал некоторые испытания, и кажется, что он более ленив без the 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() частный конструктор не является хитом, и когда я раскомментировать статический конструктор, частный конструктор всегда называется.

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

в моих попытках понять, что разница будет ли beforefieldinit сделать Я также прочитал ответ Skeet in this post попробовал его с передачей false в DoSomething() - с или без статического конструктора частный конструктор не вызывается.

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

Так в чем же ценность 'which' здесь? Похоже, что это, вероятно, «ложь». –

+0

Первый пример кода не использует метод DoSomething(), я просто вызываю 'Singleton.Stub()' из Main() .. во втором примере кода, который всегда является ложным. – BornToCode

+0

Это, вероятно, потому, что вы передаете константу методу 'DoSomething (false)', и оператор 'if' будет оптимизирован, поэтому' Singleton.Stub() 'оптимизируется/удаляется из кода. –

ответ

5

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

Это не ясно, что значение which здесь, но в основном у вас есть четыре случая:

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

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

+0

1. Почему вы предлагаете (в приведенной выше статье) добавить статический ctor для полной лености? Когда Stub вызывается без статического инициализатора типа ctor, он может запускаться со статическим ctor, который всегда будет работать - менее ленивый? 2.'Singleton.Stub not called: инициализатор типа может запускаться, но не гарантируется' - что может привести к тому, что инициализатор типа может закончиться синим? – BornToCode

+0

@BornToCode: 1) Моя полностью ленивая версия использует статический конструктор во вложенном типе, который будет инициализироваться только в том случае, если используется «Экземпляр». У вашего кода нет вложенного типа - это не тот же сценарий. 2) Когда метод запускается первым, разумно (но не обязательно) для компилятора JIT инициализировать все типы, которые * могут быть необходимы методу, и которые имеют слабые гарантии инициализации. Это означает, что нет необходимости проверять каждый раз, был ли тип * * инициализирован. –

 Смежные вопросы

  • Нет связанных вопросов^_^