2013-07-03 2 views
7

Как вы можете видеть по моему нику, я новичок на самом деле узнал о шаблоне Singleton, где у меня возникла одна проблема. Прежде чем я узнаю, что статические конструкторы всегда выполняются перед стандартными конструкторами, но в этом коде ниже результат отличается, сначала я вижу строку «Insta», а затем «Static», почему это происходит?C# - Singleton Pattern

sealed class Singleton 
{ 
    private static readonly Singleton instance; 

    private Singleton() 
    { 
     Console.WriteLine("Insta"); 
    } 

    static Singleton() 
    { 
     instance = new Singleton(); 
     Console.WriteLine("Static"); 
    } 

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

class Program 
{ 
    static void Main() 
    { 
     Singleton s1 = Singleton.Instance; 

    } 

} 
+2

Связанный: http://csharpindepth.com/Articles/General/Singleton.aspx – jbabey

+1

Не уверен, что на рассуждения ваши ожидания - «статический конструктор называется первым» не означает «весь код в статическом конструкторе, магически выполненный до всех вызовов членам класса» (конструктор экземпляра в вашем случае). –

ответ

13

Если вы будете писать

static Singleton() 
{ 
    Console.WriteLine("Static"); //THIS COMES FIRST 
    instance = new Singleton(); 

} 

вы увидите, что вы ожидаете

статическая т е р выполняется сначала, как и ожидалось, но при печати на консоли после instance = new Singleton(); линии , но эта строка выполняет экземпляр ctor, поэтому «inst».

Так поток выполнения:

  • статическая т е р
    • instance = new Singleton();
      • экземпляр CTOR печатает "Insta"
    • "статические"
+0

Правильно моя ошибка, спасибо. Но у меня есть еще один вопрос о том, что, если я напишу «private static readonly Singleton instance = new Singleton();» Будет ли компилятор переместить это выражение в static ctor или что? – CSharpBeginner

+0

@CSharpBeginner no, экземпляр Singleton будет создан при первом вызове класса, вам больше не понадобится статический конструктор – konkked

+0

Итак, эта инициализация работает так же, как статический ctor делает правильно? – CSharpBeginner

8

См. MSDN pattern here для качественного объяснения одноэлементного рисунка.

MSDN рекомендует вы должны написать его, как показано ниже, так что поточно:

using System; 

public sealed class Singleton 
{ 
    private static volatile Singleton instance; 
    private static object syncRoot = new Object(); 

    private Singleton() {} 

    public static Singleton Instance 
    { 
     get 
     { 
     if (instance == null) 
     { 
      lock (syncRoot) 
      { 
       if (instance == null) 
        instance = new Singleton(); 
      } 
     } 

     return instance; 
     } 
    } 
} 

Кстати, эта модель имеет следующие преимущества перед статическим конструктором:

инстанциации не выполняется, до тех пор, объект запрашивает экземпляр; этот подход называется ленивым экземпляром. Ленивая инстанция позволяет избежать создания ненужных синглонов при запуске приложения.

Проверьте, соответствует ли это вашим потребностям, и если да, реализуйте это решение.

+2

Что такое безопасность потока, связанная с концептуальным вопросом, подобным этому? – Raptor

+2

Я хочу представить статью MSDN о том, как реализовать одноэлементное решение.Не нужно изобретать велосипед. Поскольку он новичок, всегда хорошо иметь хорошую прочную статью, чтобы читать и понимать конкретный образец. – saamorim

+0

@saamorim: Скопируйте копию. Копирование слов и кодов MSDN – Learner

1

Сначала статический метод вызывается. Вот доказательство - изменить код к следующему:

static Singleton() 
    { 
     Console.WriteLine("Static method start"); 
     instance = new Singleton(); 
     Console.WriteLine("Static method end"); 
    }