2012-03-16 30 views
5

Przechodziłem przez następującą implementację Singleton wymienioną here. Rozumiem, że konstruktory statyczne są wykonywane przed pierwszym wywołaniem metody statycznej lub przed utworzeniem obiektu te, ale nie rozumiałem jego użycia tutaj (nawet z komentarzy). Czy ktokolwiek mógłby mi pomóc to zrozumieć?Implementacja Singleton z pustym konstruktorem statycznym

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

    // Explicit static constructor to tell C# compiler 
    // not to mark type as beforefieldinit 
    static Singleton() 
    { 
    } 

    private Singleton() 
    { 
    } 

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

Zostało to wyjaśnione w punktach poniżej, w szczególności: 'Lenistwo inicjatorów typu jest gwarantowane tylko przez .NET, gdy typ nie jest oznaczony specjalną flagą o nazwie" beforefieldinit ". Niestety, kompilator C# (przynajmniej w środowisku .NET 1.1) zaznacza wszystkie typy, które nie mają statycznego konstruktora (tj. Bloku, który wygląda jak konstruktor, ale jest oznaczony jako statyczny) jako "beforefieldinit". , chce, aby 'nowy Singleton()' został skonstruowany tak późno, jak to możliwe (leniwie), a jedynym sposobem na uzyskanie kompilatora C#, aby to zrobić, jest zapewnienie pustego konstruktora statycznego. – porges

+0

Przebacz mojej niewiedzy. Czym jest "lenistwo inicjatorów typu". Jest inicjalizacja na pierwsze żądanie? – Nemo

+0

Dokładnie. Gwarantuje to tylko taka sytuacja, w przeciwnym razie środowisko wykonawcze może uruchamiać inicjalizatory typów, kiedy tylko tego chce, na przykład po załadowaniu typu. Aby uzyskać dłuższe wyjaśnienie, patrz link w odpowiedzi Jaya. – porges

Odpowiedz

7

Statyczny konstruktor nie jest tam w porządku, że powinna ona być wywołana przed lub po cokolwiek innego, tylko jako sposób dokonania kompilator nie ustawić flagę beforefieldinit.

Więcej informacji na ten temat tutaj: What does beforefieldinit flag do?

Uzasadnieniem jest osiągnięcie miarę lenistwo w inicjalizacji obiektu singleton. Jeśli ustawiono beforefieldinit (ponieważ nie zdefiniowano żadnego konstruktora statycznego), wówczas wykonanie metody, która warunkowo odwołuje się do Singleton.Instance, prawdopodobnie zainicjuje obiekt singleton, , nawet jeśli warunek nie zostanie spełniony, a wywołanie nigdy nie zostanie wykonane.

public void Foo() 
{ 
    if (false) 
    { 
     var bar = Singleton.Instance.SomeMethod(); 
    } 
} 

Z drugiej strony, jeśli beforefieldinit nie jest (ze statycznym konstruktor definiuje - nawet pusty), a następnie wykonując ten sam sposób powoduje tylko pojedyncza przykład być inicjowany, gdy warunek jest zadowolony, a wywołanie to w rzeczywistości wykonane.

Przepis idzie podkreślić, że ta konkretna realizacja nie jest w pełni leniwa ponieważ wywołanie dowolnego inne statyczny element, który można zdefiniować w klasie singleton spowoduje również Instance zostać zainicjowany.