Quand un constructeur statique est-il appelé en C #?

88

Lorsque j'ai une classe contenant un constructeur statique, ce constructeur est-il appelé lorsque l'assembly contenant la classe est chargé pour la première fois ou lorsque la première référence à cette classe est atteinte?

Jason
la source

Réponses:

93

Lorsque la classe est accédée pour la première fois.

Constructeurs statiques (Guide de programmation C #)

Un constructeur statique est utilisé pour initialiser toutes les données statiques ou pour effectuer une action particulière qui ne doit être effectuée qu'une seule fois. Il est appelé automatiquement avant que la première instance ne soit créée ou que des membres statiques soient référencés.

Carra
la source
6
Intéressant qu'il dise "avant que la première instance ne soit créée ou que des membres statiques soient référencés". Il y a une certaine marge de manœuvre lorsqu'il est effectivement invoqué.
Tim Barrass
6
@TimBarrass, en raison d'autres exigences de spécification, s'avère que "avant" est en fait "immédiatement avant" - voir l'article de Jon Skeet référencé dans une autre réponse - stackoverflow.com/a/1437372/477420
Alexei Levenkov
A static constructor is used to initialize any static dataNON. Mieux vaut l'utiliser static initializerpour initialiser des éléments statiques.
Yousha Aleayoub
41

Ce n'est pas aussi simple que vous pourriez vous y attendre malgré une documentation simple. L'article de Jon Skeet http://csharpindepth.com/Articles/General/Beforefieldinit.aspx aborde cette question en détail.

Sommaire:

Le constructeur statique est garanti pour être exécuté immédiatement avant la première référence à un membre de cette classe - soit la création de l'instance ou la propre méthode statique / propriété de classe.

Notez que les initiateurs statiques (s'il n'y a pas de constructeur statique) garantissent d'être exécutés à tout moment avant la première référence à un champ particulier.

Greg Beech
la source
L'article mentionné est maintenant sur le site de Jon Skeet: csharpindepth.com/Articles/General/Beforefieldinit.aspx
Sudhanshu Mishra
La question suivante stackoverflow.com/questions/32525628/… montre le cas où le comportement «immédiat» est assez évident.
Alexei Levenkov
1
En fait, j'ai juste eu le cas où un constructeur statique a été appelé juste avant que la méthode Main d'une application console ne commence même à s'exécuter!
HerpDerpington
19

Le constructeur statique est appelé avant que vous n'utilisiez quoi que ce soit dans la classe, mais exactement quand cela se produit dépend de l'implémentation.

Il est garanti qu'il sera appelé avant l'accès au premier membre statique et avant la création de la première instance. Si la classe n'est jamais utilisée, le constructeur statique n'est pas du tout garanti d'être appelé.

Guffa
la source
2
Quand cela se produit n'est pas "à la hauteur de l'implémentation" si cette implémentation suit la spécification ECMA C #: "L'exécution d'un constructeur statique est déclenchée par le premier des événements suivants à se produire dans un domaine d'application: [1] Une instance du classe est créée. [2] Tous les membres statiques de la classe sont référencés. " (Section 17.11, ecma-international.org/publications/standards/Ecma-334.htm )
LukeH
1
@Luke: "Le moment exact de l'exécution du constructeur statique dépend de l'implémentation" ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html
Guffa
2
@Guffa: Cela pourrait être l'interprétation de l'auteur de l'article, mais vous ne trouverez pas ce libellé dans les versions Microsoft ou ECMA / ISO de la spécification C #.
LukeH
1

Dans le cas où une méthode statique est appelée à partir de la classe parent, le constructeur statique ne sera pas appelé, bien qu'il soit explicitement spécifié. Voici un exemple que le constructeur b n'est pas appelé si b.methoda () est appelé.

static void Main(string[] args)
{
    b.methoda();
}

class a
{
    public static void methoda()
    {
        //using initialized method data
    }
}

class b : a
{
    static b()
    {
        //some initialization
    }
}    
Andrew
la source
1

Il semble y avoir un piège avec les constructeurs statiques qui est répondu ailleurs mais qui a pris un certain temps à digérer dans une explication simple. Tous les documents et explications affirment que le constructeur statique / les initiateurs sont «garantis» de s'exécuter avant que la première classe ne soit instanciée ou que le premier champ statique ne soit référencé. Le gotcha entre lorsque vous essayez de mettre un singleton statique dans la classe qui crée une instance de lui-même (poulet / œuf). Dans ce cas, le constructeur statique finit par être appelé après le constructeur d'instance - et dans mon cas, le constructeur d'instance contenait du code qui reposait sur des données statiques.

Constructeur statique appelé après le constructeur d'instance?

Le constructeur statique peut s'exécuter après le constructeur non statique. Est-ce un bogue du compilateur?

(la réponse pour moi était de placer le singleton dans une classe distincte ou d'initialiser manuellement les données statiques dans le constructeur d'instance avant que cela ne soit requis)

Etherman
la source