c# - tipos - ¿Cómo funciona un constructor estático?
tipos de clases programacion (10)
Aquí está el orden real en el que las cosas van hacia abajo:
- Inicio de
Main
- Inicio del constructor estático
MyClass
- Fin del constructor
MyClass
estático - Start of
MyMethod
- Fin de
Main
namespace MyNameSpace
{
static class MyClass
{
static MyClass()
{
//Authentication process.. User needs to enter password
}
public static void MyMethod()
{
//Depends on successful completion of constructor
}
}
class Program
{
static void Main(string[] args)
{
MyClass.MyMethod();
}
}
}
Aquí está la secuencia que asumí
- Inicio del constructor estático
- Fin del constructor estático
- Inicio de main
- Start of MyMethod
- Fin de principal
Ahora en cualquier escenario si 4 comenzará antes de las 2 estoy atornillado. ¿Es posible?
CLR garantiza que el constructor estático se ejecuta antes de acceder a cualquier miembro estático. Sin embargo, tu diseño es un poco apestoso. Sería más sencillo hacer algo como esto:
static void Main(string[] args)
{
bool userIsAuthenticated = MyClass.AuthenticateUser();
if (userIsAuthenticated)
MyClass.MyMethod();
}
Con su diseño, si falla la autenticación, la única forma de evitar que MyMethod se ejecute es lanzando una excepción.
De acuerdo con MSDN , un constructor estático:
Se llama automáticamente a un constructor estático para inicializar la clase antes de que se cree la primera instancia o se haga referencia a cualquier miembro estático.
Por lo tanto, se llamará al constructor estático antes de que se MyClass.MyMethod()
método estático MyClass.MyMethod()
(suponiendo que no se invoque también durante la construcción estática o la inicialización del campo estático, por supuesto).
Ahora, si está haciendo algo asincrónico en ese static constructor
, entonces es su trabajo sincronizar eso.
De la MSDN (énfasis mío):
Se llama automáticamente a un constructor estático para inicializar la clase antes de que se cree la primera instancia o se haga referencia a cualquier miembro estático .
El # 3 es en realidad # 1: la inicialización estática no comienza hasta el primer uso de la clase a la que pertenece.
Es posible si se llama a MyMethod
desde el constructor estático o desde un bloque de inicialización estático. Si no MyMethod
directa o indirectamente desde tu constructor estático, estarás bien.
O podrías pasar por el depurador.
Puede garantizar que 4 siempre vendrá después de 2 (si no crea una instancia de su clase a partir de su método estático), sin embargo, lo mismo no es cierto para 1 y 3.
Se garantiza que se haya llamado al constructor de una clase estática antes de ejecutar cualquiera de sus métodos. Ejemplo:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press enter");
Console.ReadLine();
Boop.SayHi();
Boop.SayHi();
Console.ReadLine();
}
}
static class Boop
{
static Boop()
{
Console.WriteLine("Hi incoming ...");
}
public static void SayHi()
{
Console.WriteLine("Hi there!");
}
}
Salida:
Presione enter
// después de presionar enter
Hola entrante ...
¡Hola!
¡Hola!
Se llamará al constructor estático antes de que mymethod se ejecute. Sin embargo, si se atornilla si se llama 4 antes que 2, le sugiero que vuelva a pensar en su diseño. No debería estar haciendo cosas complicadas en un constructor estático de todos modos.
Usted solo hizo una pregunta aquí, pero hay una docena de preguntas que debería haber hecho, así que las responderé todas.
Aquí está la secuencia que asumí
- Inicio del constructor de la clase (también conocido como
cctor
) - Fin de cctor
- inicio de Main
- inicio de MyMethod
¿Es esto correcto?
No. La secuencia correcta es:
- Inicio de cctor para el programa, si hay uno. No hay.
- Fin del programa para el programa, si hay uno. No hay.
- Inicio de Main
- Inicio de cctor para MyClass
- Fin de cctor para MyClass
- Inicio de MyClass.MyMethod
¿Qué sucede si hay un inicializador de campo estático?
El CLR puede cambiar el orden en el que se ejecutan los inicializadores de campos estáticos en algunos casos. Vea la página de Jon sobre el tema para más detalles:
Las diferencias entre los constructores estáticos y los inicializadores de tipo
¿Es posible que se
MyMethod
a un método estático comoMyMethod
antes de que se complete elctor de esa clase?
Sí. Si el propio cctor llama a MyMethod, obviamente se llamará a MyMethod antes de que complete elctor.
El cctor no llama a MyMethod. ¿Es posible que se
MyMethod
a un método estático comoMyMethod
antes de que se complete elctor de MyClass?
Sí. Si el cctor utiliza otro tipo cuyo cctor llama a MyMethod, se llamará a MyMethod antes de que se complete MyClassCctor.
¡Ningún proveedor llama a MyMethod, directa o indirectamente! Ahora, ¿es posible que se
MyMethod
a un método estático comoMyMethod
antes de que se complete elctor de MyClass?
No.
¿Sigue siendo cierto incluso si hay múltiples hilos involucrados?
Sí. Elctor terminará en un hilo antes de que el método estático pueda invocarse en cualquier hilo.
¿Se puede llamar al cctor más de una vez? Supongamos que dos hilos hacen que se ejecute el cctor.
Se garantiza que elctor se llamará a lo sumo una vez, sin importar cuántos hilos estén involucrados. Si dos hilos llaman a MyMethod "al mismo tiempo", compiten. Uno de ellos pierde la carrera y bloquea hasta que MyClassCctor complete el hilo ganador.
¿El hilo perdedor se bloquea hasta que el cctor está listo? ¿ De verdad ?
De Verdad.
Entonces, ¿qué ocurre si elctor en el hilo ganador llama al código que bloquea un bloqueo previamente realizado por el hilo perdedor ?
Entonces tiene una condición de inversión de orden de bloqueo clásica. Los bloqueos de tu programa. Siempre.
Eso parece peligroso. ¿Cómo puedo evitar el punto muerto?
Si duele cuando lo haces, deja de hacer eso . Nunca haga algo que pueda bloquear en un cctor.
¿Es una buena idea confiar en la semántica de inicialización de cctor para imponer requisitos de seguridad complejos? ¿Y es una buena idea tener unctor que realice las interacciones del usuario?
Tampoco son buenas ideas. Mi consejo es que debe encontrar una forma diferente de garantizar que se cumplan las condiciones previas de sus métodos que afectan a la seguridad.