2017-02-14 2 views
9

Я читал учебник для реализации Singleton и кодкоторый называется первый статический конструктор или частный конструктор

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

     static Singleton() 
     { 
      Console.WriteLine("Static"); 
     } 
     private Singleton() 
     { 
      Console.WriteLine("Private"); 
     } 

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

     public void DoSomething() { 
      //this must be thread safe 
     } 
    } 

Когда я пишу Singleton.Instance, выход

Private
Статический

Я ожидал, что это будет

Статический
Частный

Причина в том, что, когда я прочитал MSDN учебник «https://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx»

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

Почему существует разница?

+0

Для одноточечного, вам не нужен статический конструктор. Создайте объект и используйте простую резьбу с помощью 'lock (object)', чтобы только один поток мог получить доступ к вашему методу. – ViVi

+0

Я начал с Locks и прочитал достаточно документации, заявляя, насколько они дороги. Следовательно, я выбрал этот код. – Rajat

+0

@ViVi этот вопрос не о том, что является лучшим способом, а просто потому, что выход «Private Static». Хороший вопрос – CodingYoshi

ответ

5

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

static Singleton() 
{ 
    instance = new Singleton(); 
    // It has to be legal to use "instance" here 
    Console.WriteLine("Static"); 
} 

Обратите внимание, что в вашем примере это существенно то, что происходит в любом случае. Инициализаторы полей по существу становятся частью конструктора; они просто выполняются первыми.

Это подтверждается сгенерированным IL:

// Static constructor 
Singleton..cctor: 
IL_0000: newobj  Singleton..ctor  //Calls private constructor first 
IL_0005: stsfld  Singleton.instance //to create .instance 
IL_000A: nop   
IL_000B: ldstr  "Static" 
IL_0010: call  System.Console.WriteLine 
IL_0015: nop   
IL_0016: ret   

Смотрите также связанные (но не дублировать) вопрос, как правило, отличный ответ Эрик Липперто здесь: Calling of Static Constructor and Instance Constructor

+0

Итак, он начинается со статического конструктора, как обычно , внутри статического конструктора ему нужен действительный экземпляр, поэтому он должен создать экземпляр поля, который снова вызывает частный конструктор. Статический -> Поле -> частный конструктор. Правильно ли я понял? –

+0

@Abdul: в принципе, да. Все это определяется во время компиляции. Это не похоже на то, что код динамически динамически определяет в статическом конструкторе, которому нужен действительный экземпляр. Код уже есть, чтобы получить его. Но да, это необходимо для инициализации поля в статическом конструкторе, который вызывает вызов конструктора экземпляра. –

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