2010-07-01 13 views
5

Quale classe statica viene inizializzata per prima se nel nostro progetto sono presenti altre classi statiche?Quale classe statica viene inizializzata per prima?

Ad esempio: il codice sottostante fornisce un'eccezione nulla.

class Program 
    { 
     static void Main(string[] args) 
     { 
      First.Write(); 
      Second.Write(); 
     } 
    } 
    static class First 
    { 
     public static int[] firstArray = new int[20]; 
     public static int[] secondArray = Second.secondArray; 
     public static void Write() 
     { 
      Console.WriteLine(firstArray.ToString()); 
      Console.WriteLine(secondArray.ToString()); 
     } 
    } 
    static class Second 
    { 
     public static int[] firstArray = First.firstArray; 
     public static int[] secondArray = new int[30]; 
     public static void Write() 
     { 
      Console.WriteLine(firstArray.ToString()); 
      Console.WriteLine(secondArray.ToString()); 
     } 
    } 

Se si presta attenzione, si vedrà che se First classe sarà l'inizializzazione in modo secondArray campo della Second sarebbe nullo. Ma se la classe Second inizializzasse per prima, allora la classe SecondfirstArray sarebbe nullo. Sto cercando di dire che l'inizializzazione prima produce risultati diversi.

Penso che sia una domanda astratta sul mio progetto. Lo incontro mentre cerco di capire perché sto ottenendo risultati inaspettati.

risposta

10

First inizierà per inizializzare, assegnare firstArray, quindi si noti che richiede Second essere inizializzato in modo da ottenere il valore iniziale di secondArray.

Second inizierà l'inizializzazione e quindi noterà che richiede l'inizializzazione per primo. Tuttavia, il CLR noterà che First è già inizializzazione nel thread corrente, quindi non verrà bloccato. L'inizializzazione di Second verrà completata e quindi l'inizializzazione di First verrà completata.

Fortunatamente, il campo che ha richiesto Second è già stato assegnato, quindi la "cosa giusta" si verifica.

Questo è tutto molto bene se Firsteffettivamente inizia l'inizializzazione prima. Tuttavia, poiché nessuna delle due classi ha un costruttore statico, è possibile che Second inizi a inizializzarsi per primo ... inizierebbe quindi a inizializzare First, che rileverebbe che Second è già in fase di inizializzazione e prende il valore corrente di Second.secondArray (null) per First.secondArray. Questa sarebbe una brutta cosa. Si noti che il tempo di inizializzazione per i tipi senza costruttori statici ha changed in .NET 4 - non in modo spec-breaking, ma possibilmente in un modo di rottura del codice esistente.

Se entrambi First e Second avevano costruttori statici, quindi First sarebbe inizializzato prima, in quanto questo è il primo classe che Main tocchi.

Morale della risposta: non farlo. Gli inizializzatori di tipo che si riferiscono l'un l'altro sono molto soggetti a errori. Per un altro esempio, vedi il talk di NDC 2010 di Eric Lippert e Neal Gafter, "C# Puzzlers" che può essere visualizzato sullo NDC video page.

+0

Fa la garanzia standard di quest'ordine? La mia ipotesi era che ogni classe inizializza ad un certo indefinito prima del primo accesso, il che trasforma questo in un ciclo di dipendenze che viene risolto casualmente. –

+0

@Tim: Ho aggiornato la mia risposta - senza costruttori statici, l'ordine è effettivamente indefinito. –

+0

Con debugger collegato a VS2005, si verifica una cosa brutta - 'Second.firstArray' viene impostato su' null' – AakashM

0

Non credo ci sia alcuna garanzia su quale tipo statico sia inizializzato per primo. Per garantire i campi sono inizializzati correttamente in questo modo, si avrebbe bisogno di aggiungere un costruttore statico, ad esempio:

static class Second 
{ 
    public static int[] firstArray = First.firstArray; 
    public static int[] secondArray = new int[30]; 

    static Second() { } 

    public static void Write() 
    { 
     Console.WriteLine(firstArray.ToString()); 
     Console.WriteLine(secondArray.ToString()); 
    } 
} 

Ora, quando si esegue nuovamente la stessa cosa, funziona ...

Problemi correlati