2016-03-21 19 views
10

Sto cercando di capire perché questa è una corretta attuazione del pattern Singleton:Perché l'implementazione Singleton in C# 6.0 non ha bisogno del flag beforefieldinit?

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

    private Singleton() { } 

    // methods 
} 

cosa circa la bandiera beforefieldinit? Secondo Jon Skeet article:

La pigrizia di tipo initializers è garantita solo dalla NET quando il tipo non è contrassegnata con un flag speciale chiamato beforefieldinit. Sfortunatamente, il compilatore C# (come previsto nel runtime .NET 1.1, almeno) contrassegna tutti i tipi che non hanno un costruttore statico (cioè un blocco che assomiglia a un costruttore ma è contrassegnato come statico) come beforefieldinit.

Il costruttore statico non è necessario nella versione più recente di C#?

Il codice sopra riportato è l'implementazione di SystemClock nel progetto NodaTime, di Jon Skeet. "

EDIT codice Jon Skeet di rinvio (perché sto menzionare questo 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

Che dire di quella bandiera? Non capisco la domanda. – usr

+0

@usr vedere la modifica :) –

+0

C'è un problema di progettazione del linguaggio C# in sospeso per specificare esplicitamente il comportamento di 'beforefieldinit': https://github.com/dotnet/roslyn/issues/4448 (fyi) – usr

risposta

10

sono entrambi corretti implementazioni Singleton. Se hai bisogno del costruttore statico solo dipende da quanto ti preoccupi della totale pigrizia. Se davvero, davvero non vuoi che il singleton sia istanziato fino a quando non viene usato da un chiamante, dovresti avere un costruttore statico - o usare Lazy<T>. Puoi anche utilizzare un costruttore statico nel codice C# 6, ovviamente:

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

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

    // methods 
} 
+0

ora il compilatore non segna di default con il costruttore statico beforefieldinit vero? –

+0

@ EʜsᴀɴSᴀᴊᴊᴀᴅ: Non sono a conoscenza di alcun cambiamento su quel fronte, ma controllerò. –

+0

@ EʜsᴀɴSᴀᴊᴊᴀᴅ: Suggerisco di fare una nuova domanda molto specifica. Ho appena confermato che il compilatore C# aggiunge ancora 'beforefieldinit' a meno che non ci sia un costruttore statico. –