Qual è l'ordine di inizializzazione della variabile statica tra le classi in C#?

Qual è l'ordine di inizializzazione della variabile statica tra le classi in C#?

Va bene che un tipo dipenda dall'inizializzazione di un altro tipo, a patto di non finire in un ciclo.

Fondamentalmente questo va bene:

public class Child
{
    static Child() {} // Added static constructor for extra predictability
    public static readonly int X = 10;
}

public class Parent
{
    static Parent() {} // Added static constructor for extra predictability
    public static readonly int Y = Child.X;
}

Il risultato è ben definito. Child Gli inizializzatori di variabili statiche di ' vengono eseguiti prima del primo accesso a qualsiasi campo statico della classe, come da sezione 10.5.5.1 delle specifiche.

Questo non è però:

public class Child
{
    public static readonly int Nasty = Parent.Y;
    public static readonly int X = 10;
}

public class Parent
{
    public static readonly int Y = Child.X;
}

In quest'ultimo caso, tu o finisci con Child.Nasty=0 , Parent.Y=10 , Child.X=10 o Child.Nasty=0 , Parent.Y=0 , Child.X=10 a seconda della classe a cui si accede per prima.

Accesso a Parent.Y first inizierà l'inizializzazione di Parent primo, che attiva l'inizializzazione di Child . L'inizializzazione di Child si renderà conto che Parent deve essere inizializzato, ma il CLR sa che è già stato inizializzato, quindi continua a prescindere, portando al primo set di numeri, perché Child.X finisce per essere inizializzato prima che il suo valore venga utilizzato per Parent.Y .

Accesso a Child.Nasty inizierà l'inizializzazione di Child prima, che poi inizierà a inizializzare Parent . L'inizializzazione di Parent si renderà conto che Child deve essere inizializzato, ma il CLR sa che è già stato inizializzato, quindi continua a prescindere, portando al secondo set di numeri.

Non farlo.

EDIT:Ok, spiegazione più dettagliata, come promesso.

Quando viene inizializzato un tipo?

Se un tipo ha un costruttore statico , verrà inizializzato solo quando viene utilizzato per la prima volta (o quando viene fatto riferimento a un membro statico o quando viene creata un'istanza). Se non avere un staticconstructor, può essere inizializzato prima. In teoria, potrebbe essere inizializzato anche in un secondo momento; potresti teoricamente chiamare un costruttore o un metodo statico senza che le variabili statiche vengano inizializzate - ma deve essere inizializzato prima di fare riferimento alle variabili statiche.

Cosa succede durante l'inizializzazione?

Innanzitutto, tutte le variabili statiche ricevono i loro valori predefiniti (0, nullecc).

Quindi le variabili statiche del tipo vengono inizializzate in ordine testuale. Se l'espressione di inizializzazione per una variabile statica richiede l'inizializzazione di un altro tipo, l'altro tipo verrà completamente inizializzato prima che il valore della variabile venga assegnato -a meno che quel secondo tipo è già in fase di inizializzazione (a causa di una dipendenza aciclica). In sostanza, un tipo è:

  • Già inizializzato
  • Inizializzazione in corso
  • Non inizializzato

L'inizializzazione viene attivata solo se il tipo non è inizializzato. Ciò significa che quando ci sono dipendenze cicliche, è possibile osservare il valore di una variabile statica prima che il suo valore iniziale sia stato assegnato . Questo è ciò che il mio Child /Parent esempio mostra.

Dopo che tutti gli inizializzatori di variabili statiche sono stati eseguiti, viene eseguito staticconstructor.

Vedi la sezione 10.12 delle specifiche C# per maggiori dettagli su tutto questo.

A grande richiesta, ecco la mia risposta originale quando pensavo che la domanda riguardasse l'ordine di inizializzazione delle variabili statiche all'interno di una classe :

Le variabili statiche vengono inizializzate in ordine testuale, come da sezione 10.5.5.1 della specifica C#:

Nota che i tipi parziali rendono questo più complicato in quanto non esiste un "ordine testuale" canonico della classe.