2016-03-21 26 views
10

Próbuję zrozumieć, dlaczego jest to poprawna implementacja wzorca Singleton:Dlaczego wdrożenie singleton w C# 6.0 nie wymaga flagi beforefieldinit?

public sealed class Singleton : ISingleton 
{ 
    public static Singleton Instance { get; } = new Singleton(); 

    private Singleton() { } 

    // methods 
} 

co z flagą beforefieldinit? Według Jon Skeet article:

Lenistwo typu inicjalizatorów jest zagwarantowane tylko przez .NET, gdy typ nie jest oznaczony specjalną flagę zwanego beforefieldinit. Niestety, kompilator C# (przynajmniej w środowisku wykonawczym .NET 1.1) zaznacza wszystkie typy, które nie mają statycznego konstruktora (tj. Bloku, który wygląda jak konstruktor, ale jest oznaczony statycznie) jako beforefieldinit.

Czy konstruktor statyczny nie jest potrzebny w najnowszej wersji C#?

Powyższy kod jest implementacją SystemClock w projekcie NodaTime autorstwa Jona Skeeta. "

EDIT kod Jon Skeet odsyłające (dlaczego ja wspomnieć tę flagę beforefieldinit):

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

Co z tą flagą? Nie rozumiem tego pytania. – usr

+0

@usr zobacz edycję :) –

+0

Istnieje wyjątkowa kwestia projektowania języka C# dla jawnego określania zachowania 'beforefieldinit': https://github.com/dotnet/roslyn/issues/4448 (fyi) – usr

Odpowiedz

10

Obie są poprawne implementacje Singleton. To, czy potrzebujesz statycznego konstruktora, zależy od tego, jak bardzo zależy Ci na pełnym lenistwie. Jeśli naprawdę, naprawdę nie chcesz, aby singleton był tworzony, dopóki nie zostanie użyty przez osobę dzwoniącą, powinieneś mieć konstruktora statycznego - lub użyć Lazy<T>. Można również użyć konstruktora statycznego w kodzie C# 6, oczywiście:

public sealed class Singleton : ISingleton 
{ 
    public static Singleton Instance { get; } = new Singleton(); 

    static Singleton() { } 
    private Singleton() { } 

    // methods 
} 
+0

teraz kompilator nie zaznacza domyślnie konstruktora statycznego przed właściwym polem? –

+0

@ EʜsᴀɴSᴀᴊᴊᴀᴅ: Nie jestem świadomy żadnych zmian na tym froncie, ale sprawdzę. –

+0

@ EʜsᴀɴSᴀᴊᴊᴀᴅ: Sugeruję, abyś wtedy zadał nowe, bardzo konkretne pytanie. Właśnie potwierdziłem, że kompilator C# nadal dodaje 'beforefieldinit', chyba że jest konstruktor statyczny. –