2010-10-29 4 views
4

J'ai une application Web ASP.NET qui commence à montrer un comportement très étrange. Voici quelques exemples de code:L'initialisateur de champ statique s'exécute avant Application_start, parfois

// in Bar.cs 
public class Bar { 
    public static Baz baz = Something.Step2(); 
} 

// in Global.asax 
public void Application_Start(...) { 
    Something.Step1(); 
} 

La version courte de l'histoire est la suivante: Sur certaines machines, Something.Step2 est exécutée avant Something.Step1 et lancer une exception unhandleable. Sur les autres machines, l'étape 1 s'exécute correctement avant l'étape 2. Global.asax et tous les objets qu'il utilise ne se réfèrent pas du tout à Bar.

Quand les champs statiques sont-ils supposés s'exécuter par rapport à d'autres éléments de programmation? Pourquoi deux machines (Win7 64 bits, à la fois avec .NET 4.0, même version IIS, etc.) exécuteraient-elles des choses dans des ordres différents? La commande est cohérente sur chaque machine aussi. Sur ma machine, exécute toujours Step2 avant l'étape 1, mais sur l'ordinateur de mon collègue, exécute toujours et exécute Step1 avant l'étape 2.

Aide très appréciée.

Mise à jour J'ai trouvé la cause première de l'accès à mon champ statique. La classe "Bar" de mon exemple est en fait un module d'authentification personnalisé, et est référencée dans web.config en tant que gestionnaire d'authentification sous System.webServer. Si je supprime cette ligne de web.config, mon système appelle d'abord Step1 et n'appelle jamais Step2. Ma question change subtilement: "Pourquoi web.config fait-il exploser mes initialiseurs statiques, et pourquoi les déclenche-t-il avant l'exécution de Application_Start?"

Répondre

6

Les initialiseurs de champ statique, lorsque vous ne disposez pas d'un constructeur statique, sont initialisés à un moment "dépendant de l'implémentation" avant le premier accès. Cela signifie qu'ils peuvent être initialisés à tout moment - vous ne pouvez pas compter sur l'initialisation de Bar.Baz pour se produire la première fois que vous utilisez Bar. L'ajout d'un constructeur statique à Bar va changer le comportement de ceci pour être plus de ce que vous attendez.

Pour en savoir plus, lisez la spécification de langage C#, section 10.5.5.1:

10.5.5.1 initialisation statique champ

Le champ statique initializers variables d'une classe correspond à une séquence de tâches qui sont exécutées dans l'ordre textuel dans lequel elles apparaissent dans la déclaration de classe. Si un constructeur statique (§10.12) existe dans la classe, l'exécution des initialiseurs de champs statiques se produit immédiatement avant l'exécution de ce constructeur statique. Sinon, les initialiseurs de champ statique sont exécutés à un moment dépendant de l'implémentation avant la première utilisation d'un champ statique de cette classe.

Aussi, voir 10.2, pour plus de détails sur les constructeurs statiques:

Le constructeur statique pour un type de classe fermée exécute au plus une fois dans un domaine d'application donnée. L'exécution d'un constructeur statique est déclenchée par l'apparition du premier des événements suivants dans un domaine d'application:

· Une instance du type de classe est créée.

· Les membres statiques du type de classe sont référencés.

Cela dit, s'il y a initialisation déterministe nécessaire, je recommande fortement l'ajout d'un constructeur statique à Something et faire l'initialisation correctement là-bas. En plus de fournir une garantie de l'ordre d'initialisation dans ce cas, il empêchera l'utilisation de Something par une autre classe de provoquer la rupture de votre code dans le futur.

+0

Avez-vous un lien vers la spécification que vous regardez? La version que je suis en train de lire n'a pas de section 10.5.5. Merci. – Whiteknight

+0

@Whiteknight: Je regarde la spécification C# 4: http://go.microsoft.com/fwlink/?LinkId=199552 (Vous pouvez le trouver sur http://msdn.microsoft.com/fr-fr/ library/ms228593.aspx) La spécification C# 3 formulé différemment, mais les mêmes problèmes existaient dans les versions antérieures. –

+0

Merci pour la réponse, Reed. Je regarde maintenant le même texte que vous. Cependant, cela ne répond pas vraiment à la question sous-jacente: Pourquoi Application_Start ne s'exécute-t-il pas en premier sur mon site Web, et pourquoi le comportement de commande est-il si différent sur deux machines avec des environnements presque identiques? – Whiteknight

Questions connexes