2010-07-01 3 views
5

Quelle classe statique s'initialise en premier si nous avons encore une classe statique dans notre projet?Quelle classe statique est initialisée en premier?

Par exemple: Le code ci-dessous donne une exception nulle.

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()); 
     } 
    } 

Si vous faites attention, vous verrez que si First classe va s'initialiser si secondArray champ de Second serait nulle. Mais si la classe Second s'initialise en premier, la classe SecondfirstArray sera nulle. J'essaie de dire que ce qui initialise en premier produit des résultats différents. Je pense que c'est une question abstraite à propos de mon projet. Je le rencontre en essayant de comprendre pourquoi je reçois des résultats inattendus.

Répondre

10

First commencera à initialiser, attribuer firstArray, puis notez qu'il faut Second être initialisé afin d'obtenir la valeur initiale de secondArray.

Second commence à s'initialiser, puis remarque qu'il nécessite l'initialisation de First. Cependant, le CLR remarquera que First est déjà en train de s'initialiser dans le thread en cours, donc il ne bloquera pas. L'initialisation de Second se terminera, puis l'initialisation de First sera terminée.

Heureusement, le champ dont Second a déjà besoin a déjà été affecté, donc la "bonne chose" se produit.

Tout est très bien si Firsteffectivement commence l'initialisation en premier. Cependant, comme aucune des classes n'a de constructeur statique, il est possible que Second commence à s'initialiser en premier ... il commencera alors à initialiser First, ce qui indiquerait que Second est déjà en cours d'initialisation et prend la valeur actuelle de Second.secondArray (null) pour First.secondArray. Ce serait une mauvaise chose. Notez que le timing d'initialisation pour les types sans constructeurs statiques a changed in .NET 4 - pas d'une manière qui brise les specs, mais peut-être d'une manière qui brise le code existant.

Si les deux First et Second avaient des constructeurs statiques, alors First serait initialisé d'abord, comme c'est la première classe que Main touche.

Moralité de la réponse: ne pas faire. Les initialiseurs de type qui se réfèrent les uns aux autres sont très sujets aux erreurs. Pour un autre exemple, voir le discours NDC 2010 d'Eric Lippert et Neal Gafter, "C# Puzzlers", qui peut être consulté sur le NDC video page.

+0

Est-ce que la garantie norme cet ordre? Ma conjecture était que chaque classe initialise à un certain indéfini avant le premier accès, qui le transforme en un cycle de dépendance qui se résout aléatoirement. –

+0

@Tim: J'ai mis à jour ma réponse - sans constructeur statique, la commande est en effet indéfinie. –

+0

Avec débogueur attaché à VS2005, une mauvaise chose se produit - 'Second.firstArray' est mis à' null' – AakashM

0

Je ne crois pas qu'il existe une garantie quant au type statique initialisé en premier. Pour assurer que les champs sont initialisés correctement cette façon, vous aurez besoin d'ajouter un constructeur statique, par exemple:

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()); 
    } 
} 

Maintenant, lorsque vous exécutez à nouveau la même chose, cela fonctionne ...

Questions connexes