Constructeurs statiques en C#
On m’a posé une question il y a quelques temps :
« Et en C#, il y a l’équivalent des blocs static de Java ? »
La réponse est oui. En C# on peut définir des constructeurs statiques qui seront exécutés lors du premier des deux événements suivants :
- Une instance du type est crée.
- Un membre statique du type est accédé.
Le code suivant est un exemple, qui montre comment implémenter le pattern singleton en utilisant un tel constructeur :
public class Singleton { private int useless; private static readonly Singleton instance; private Singleton() { } public static Singleton Instance { get { return instance; } } // Constructeur statique. static Singleton() { instance = new Singleton(); instance.useless = instance.GetHashCode(); } }
La syntaxe est la même que pour un constructeur, sauf qu’il n’est plus nécessaire de définir le modificateur d’accès. Ces constructeurs sont utiles car ils permettent de réaliser des initialisations qui sont impossibles via les variable initializers. Néanmoins, si un type possède les deux, c’est le constructeur statique qui sera exécuté en dernier.
Petit QCM
Considérons les deux classes suivantes :
public class Brigitte { public static string Name = Gustave.Name; static Brigitte() { Name = "Brigitte"; } } public class Gustave { public static string Name = Brigitte.Name; static Gustave() { Name = "Gustave"; } }
Et le test unitaire suivant :
[Test] public void BrigitteAndGustave() { Assert.AreEqual("Brigitte", Brigitte.Name); Assert.AreEqual("Gustave", Gustave.Name); }
Choisissez la réponse correcte :
- Le code ne compile pas.
- Le test ne passe pas à cause de la première assertion.
- Le test ne passe pas à cause de la seconde assertion.
- Le test ne passe pas car une
StackOverFlowException
est levée. - Le test passe.
Il me semble que, tout comme pour les initialisations par défaut et les constructeurs, l’ordre d’affectation sera le suivant:
public static string Name = XXX;
puis
static Brigitte(){ Name = YYY; }
J’en déduis que Brigitte.Name vaudra « Brigitte ».
Mais comme l’appelle au corps static de Brigitte provoque aussi celui de Gustave…
Je n’en suis pas convaincu mais je dirais que le test passe (réponse 5, mais quelque chose me dit que c’est soit la réponse 2 ou 3…).
Là comme ça je dirais 5 aussi… mais par contre je ne suis pas du tout sur du résultat des asserts…
«En C# on peut définir des constructeurs statiques qui seront exécutés lors du premier accès à un membre statique de la classe.»
En fait ils sont exécutés la première fois que le JIT trouve n’importe quelle référence à la classe.
Grozeille, Romain> Bravo, vous êtes de vrais petits compilateurs… Si vous voulez voir comment est gérée la dépendance circulaire, vous pouvez lancer une session de debug :’)
Jb> Qu’entends-tu par n’importe quelle référence de la classe ?
J’ai oublié de préciser qu’à l’instar des variable initializers statiques, la première instanciation d’un objet peut évidemment provoquer l’exécution du constructeur statique de son type si elle a lieu avant qu’un membre statique de ce type ne soit référencé.
Est-ce à ça que tu fais allusion ?