¿Cuándo se llama a un constructor estático en C #?

88

Cuando tengo una clase que contiene un constructor estático, ¿se llama a ese constructor cuando el ensamblado que contiene la clase se carga por primera vez o cuando se golpea la primera referencia a esa clase?

Jason
fuente

Respuestas:

93

Cuando se accede a la clase por primera vez.

Constructores estáticos (Guía de programación de C #) Static Constructors (C # Programming Guide)

Un constructor estático se usa para inicializar cualquier dato estático o para realizar una acción particular que necesita realizarse una sola vez. Se llama automáticamente antes de que se cree la primera instancia o se haga referencia a cualquier miembro estático.

Carra
fuente
6
Es interesante que diga "antes de que se cree la primera instancia o se haga referencia a cualquier miembro estático". Hay cierto margen de maniobra cuando realmente se invoca.
Tim Barrass
6
@TimBarrass debido a algunos otros requisitos de especificación resulta que "antes" es en realidad "inmediatamente antes"; consulte el artículo de Jon Skeet al que se hace referencia en otra respuesta - stackoverflow.com/a/1437372/477420
Alexei Levenkov
A static constructor is used to initialize any static dataNO. Es mejor usarlo static initializerpara inicializar cosas estáticas.
Yousha Aleayoub
41

No es tan simple como cabría esperar a pesar de la documentación sencilla. El artículo de Jon Skeet http://csharpindepth.com/Articles/General/Beforefieldinit.aspx aborda esta pregunta en detalle.

Resumen:

Se garantiza que el constructor estático se ejecutará inmediatamente antes de la primera referencia a un miembro de esa clase, ya sea la creación de una instancia o el propio método / propiedad estática de la clase.

Tenga en cuenta que los iniciadores estáticos (si no hay un constructor estático) se garantiza que se ejecutarán en cualquier momento antes de la primera referencia a un campo en particular.

Greg Beech
fuente
El artículo mencionado está ahora en el sitio de Jon Skeet: csharpindepth.com/Articles/General/Beforefieldinit.aspx
Sudhanshu Mishra
La siguiente pregunta stackoverflow.com/questions/32525628/… demuestra el caso en el que el comportamiento "inmediato" es bastante obvio.
Alexei Levenkov
1
De hecho, acabo de tener el caso en el que se llamó a un constructor estático justo antes de que el método Main de una aplicación de consola comenzara a ejecutarse.
HerpDerpington
19

El constructor estático se llama antes de usar cualquier cosa en la clase, pero exactamente cuándo sucede eso depende de la implementación.

Se garantiza que se llamará antes de que se acceda al primer miembro estático y antes de que se cree la primera instancia. Si la clase nunca se usa, no se garantiza que se llame al constructor estático.

Guffa
fuente
2
Cuando sucede, no "depende de la implementación" si esa implementación sigue la especificación ECMA C #: "La ejecución de un constructor estático se desencadena por el primero de los siguientes eventos que ocurren dentro de un dominio de aplicación: [1] Una instancia del se crea la clase. [2] Se hace referencia a cualquiera de los miembros estáticos de la clase ". (Sección 17.11, ecma-international.org/publications/standards/Ecma-334.htm )
LukeH
1
@Luke: "El tiempo exacto de ejecución del constructor estático depende de la implementación" ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html
Guffa
2
@Guffa: Esa podría ser la interpretación del autor del artículo, pero no encontrará esa redacción en las versiones de Microsoft o ECMA / ISO de la especificación C #.
LukeH
1

En caso de que se llame al método estático desde la clase principal, no se llamará al constructor estático, aunque se especifique explícitamente. Aquí hay un ejemplo de que no se llama al constructor b si se llama a b.methoda ().

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

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

class b : a
{
    static b()
    {
        //some initialization
    }
}    
Andrés
fuente
1

Parece haber un problema con los constructores estáticos que se responde en otro lugar, pero tomó un tiempo para digerir en una explicación simple. Todos los documentos y explicaciones afirman que el constructor estático / inicializadores está "garantizado" para ejecutarse antes de que se cree una instancia de la primera clase o se haga referencia al primer campo estático. El problema aparece cuando intentas poner un singleton estático en la clase que crea una instancia de sí mismo (gallina / huevo). En este caso, el constructor estático termina siendo llamado después del constructor de instancia, y en mi caso, el constructor de instancia contenía código que se basaba en algunos datos estáticos.

¿Se llama al constructor estático después del constructor de instancia?

El constructor estático puede ejecutarse después del constructor no estático. ¿Es esto un error del compilador?

(la respuesta para mí fue poner el singleton en una clase separada o inicializar manualmente los datos estáticos en el constructor de la instancia antes de que sea necesario)

Etherman
fuente