2013-07-03 15 views
7

Jak widać z mojego nicka jestem nowicjuszem, ucząc się o wzorze Singleton, gdzie mam jeden problem. Zanim dowiem się, że konstruktory statyczne są zawsze wykonywane przed standardowymi konstruktorami, ale w poniższym kodzie wynik jest inny, najpierw widzę ciąg "Insta", a następnie "Statyczny", dlaczego tak się dzieje?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

powiązanymi: http://csharpindepth.com/Articles/General/Singleton.aspx – jbabey

+1

Nie wiesz o uzasadnieniu swojej oczekiwaniu - „statyczny konstruktor nazywa pierwszy” nie oznacza "całego kodu w konstrukcie statycznym wykonanym magicznie przed wszystkimi wywołaniami do członków klasy" (konstruktor instancji w twoim przypadku). –

Odpowiedz

13

Jeśli napiszesz

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

} 

by zobaczyć, co można oczekiwać

statyczny konstruktor jest wykonywany w pierwszym, zgodnie z oczekiwaniami, ale drukowanie na konsoli po linijka instance = new Singleton(); , ale ta linia wykonuje instancję ctor, więc "inst".

Więc przepływu wykonanie:

  • statyczny konstruktor
    • instance = new Singleton();
      • drukuje instancja konstruktor "Insta"
    • "statyczne"
+0

Dobra, moja wina, dzięki. Ale mam jeszcze jedno pytanie, co jeśli piszę "prywatną statyczną, tylko do odczytu instancję Singleton = new Singleton();" Czy kompilator przeniesie to wyrażenie do statycznego ctor lub co? – CSharpBeginner

+0

@CSharpBeginner nie, instancja Singleton zostanie skonstruowana przy pierwszym wywołaniu klasy, nie będziesz już potrzebował statycznego konstruktora. – konkked

+0

Więc ta inicjalizacja działa w ten sam sposób, w jaki statyczny ctor ma rację? – CSharpBeginner

8

Zobacz opis jakości singleton pod numerem MSDN pattern here.

MSDN zaleca należy ją napisać jak poniżej, więc jest wątek bezpieczne:

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

Nawiasem mówiąc, ten wzór ma następującą przewagę nad konstruktora statycznego:

konkretyzacji nie jest wykonywana dopóki obiekt prosi o instancję; to podejście jest określane jako leniwe tworzenie instancji. Leniwe tworzenie instancji pozwala uniknąć tworzenia niepotrzebnych singletonów po uruchomieniu aplikacji.

Sprawdź, czy to zależy od twoich potrzeb, a jeśli tak, zastosuj to rozwiązanie.

+2

Co ma wspólnego bezpieczeństwo wątków z pytaniem koncepcyjnym, takim jak ten? – Raptor

+2

Moim celem jest przedstawienie artykułu MSDN w jaki sposób wdrożyć rozwiązanie singleton.Nie trzeba wymyślać koła. Ponieważ jest początkującym, zawsze dobrze jest mieć dobry solidny artykuł do czytania i rozumienia określonego wzorca. – saamorim

+0

@saamorim: Kopiuj kopię. Kopiowanie słów i kodów MSDN – Learner

1

Metoda statyczna jest wywoływana jako pierwsza. Oto dowód - zmień swój kod na następujący:

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