Pregunta

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í.

  1. Inicio del constructor estático.
  2. Fin del constructor estático
  3. inicio de principal
  4. Inicio de Mi Método
  5. Fin de principal

Ahora, en cualquier escenario, si 4 comienza antes que 2, estoy jodido.¿Es posible?

¿Fue útil?

Solución

Aquí solo hizo una pregunta, pero hay una docena de preguntas que debería haber hecho, así que las responderé todas.

Aquí está la secuencia que asumí

  1. Inicio del constructor de la clase (también conocido como cctor)
  2. Fin de cctor
  3. inicio de Main
  4. inicio de MyMethod

¿Es esto correcto?

No. La secuencia correcta es:

  1. Inicio de cctor para el programa, si hay uno. No lo hay.
  2. Fin de cctor para el programa, si hay uno. No lo hay.
  3. Inicio de Main
  4. Inicio de cctor para MyClass
  5. Fin de cctor para MyClass
  6. Inicio de MyClass.MyMethod

¿Qué pasa si hay un inicializador de campo estático?

El CLR puede cambiar el orden en el que se ejecutan los inicializadores de campo estático en algunos casos. Consulte la página de Jon sobre el tema para obtener más detalles:

Las diferencias entre constructores estáticos e inicializadores de tipo

¿Es posible alguna vez llamar a un método estático como MyMethod antes de que se complete el cctor de esa clase?

Sí. Si el propio cctor llama a MyMethod, obviamente se llamará a MyMethod antes de que se complete el cctor.

El cctor no llama a MyMethod. ¿Es posible alguna vez llamar a un método estático como MyMethod antes de que se complete el cctor de MyClass?

Sí. Si el cctor usa otro tipo cuyo cctor llama a MyMethod, entonces se llamará a MyMethod antes de que se complete el cctor de MyClass.

¡Ningún actor llama a MyMethod, directa o indirectamente! Ahora bien, ¿es posible que se llame a un método estático como MyMethod antes de que se complete el cctor de MyClass?

No.

¿Sigue siendo cierto incluso si hay varios subprocesos involucrados?

Sí. El cctor terminará en un hilo antes de que se pueda llamar al método estático en cualquier hilo.

¿Se puede llamar al cctor más de una vez? Suponga que dos subprocesos hacen que se ejecute el cctor.

Se garantiza que el cctor se llamará como máximo una vez, sin importar cuántos subprocesos estén involucrados. Si dos subprocesos llaman a MyMethod "al mismo tiempo", corren. Uno de ellos pierde la carrera y bloquea hasta que el cctor MyClass completa el hilo ganador.

¿El hilo perdedor bloquea hasta que el cctor está listo? ¿De verdad ?

De verdad.

Entonces, ¿qué pasa si el director del subproceso ganador llama al código que bloquea un bloqueo tomado previamente por el subproceso perdedor ?

Entonces tienes una condición clásica de inversión de orden de bloqueo. Su programa se bloquea. Para siempre.

Eso parece peligroso. ¿Cómo puedo evitar el punto muerto?

Si te duele cuando haces eso, entonces deja de hacerlo . Nunca hagas algo que pueda bloquear un cctor.

¿Es una buena idea confiar en la semántica de inicialización de cctor para hacer cumplir requisitos de seguridad complejos? ¿Y es una buena idea tener un director que interactúe con el usuario?

Tampoco las buenas ideas. Mi consejo es que debería encontrar una forma diferente de asegurarse de que se cumplan las condiciones previas de sus métodos que afectan la seguridad.

Otros consejos

De acuerdo con la MSDN, un constructor estático:

Se llama automáticamente un constructor estático para inicializar la clase antes de crear la primera instancia o se hace referencia a cualquier miembro estático.

Entonces el constructor estático será llamado antes que el método estático. MyClass.MyMethod() se invoca (suponiendo que no también invocado durante la construcción estática o la inicialización del campo estático, por supuesto).

Ahora, si estás haciendo algo asíncrono en eso static constructor, entonces es tu trabajo sincronizarlo.

El n. ° 3 es en realidad el n. ° 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 invoca MyMethod directa o indirectamente desde su constructor estático, debería estar bien.

De la documentación (el énfasis es mío):

Se llama automáticamente a un constructor estático para inicializar la clase antes de que se cree la primera instancia o cualquier miembro estático es referenciado .

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, no ocurre lo mismo con 1 y 3.

Se llamará al constructor estático antes de que se ejecute mymethod.Sin embargo, si está jodido si se llama 4 antes que 2, le sugiero que reconsidere su diseño.De todos modos, no debería estar haciendo cosas complicadas en un constructor estático.

El CLR garantiza que el constructor estático se ejecuta antes de que se acceda a cualquier miembro estático.Sin embargo, tu diseño huele un poco mal.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 la autenticación falla, la única forma de evitar que MyMethod se ejecute es lanzando una excepción.

Se garantiza que se haya llamado al constructor de una clase estática antes de que se ejecute 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!");
    }
}

Resultado:

Presione enter

// después de presionar enter

Hola, entrante ...

¡Hola!

¡Hola!

Este es el orden real en el que se realizan las cosas:

  1. Inicio de Main
  2. Inicio del constructor estático MyClass
  3. Fin del constructor estático MyClass
  4. Inicio de MyMethod
  5. Fin de Main

O puede pasar por el depurador.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top