2009-04-02 25 views
18

¿Se debe completar la inicialización del campo estático antes de llamar al constructor?¿Cómo funciona la inicialización del campo estático en C#?

El siguiente programa proporciona resultados que me parecen incorrectos.

new A() 
_A == null 
static A() 
new A() 
_A == A 

El código:

public class A 
{ 
    public static string _A = (new A()).I(); 

    public A() 
    { 
     Console.WriteLine("new A()"); 
     if (_A == null) 
      Console.WriteLine("_A == null"); 
     else 
      Console.WriteLine("_A == " + _A); 
    } 

    static A() 
    { 
     Console.WriteLine("static A()"); 
    } 

    public string I() 
    { 
     return "A"; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var a = new A(); 
    } 
} 

Respuesta

22

Esto es correcto.

Tus inicializadores estáticos, luego el constructor estático se ejecuta antes que tu constructor estándar, pero cuando se ejecuta, usa una nueva A(), por lo que pasa por tu ruta de constructor no estática. Esto causa los mensajes que ves.

Aquí es la ruta completa de la ejecución:

La primera vez que la llamada var a = new A(); en su programa, esta es la primera vez que se accede A.

Esto disparar la inicialización estática de A._A

En este punto, A._A construye con _A = (new A()).I();

Esto golpea


Console.WriteLine("new A()"); 
if (_A == null) 
    Console.WriteLine("_A == null");   

ya que en este punto, no ha sido _A establecer con el tipo devuelto, construido (aún).

A continuación, se ejecuta el constructor estático A { static A(); }. Esto imprime el mensaje "estático A()".

Finalmente, se ejecuta su instrucción original (var a = new A();), pero en este punto, las estáticas están construidas, por lo que obtendrá la impresión final.

+0

Dang! ¡Pásame! –

+0

Con todo respeto ... el constructor estático no se ejecuta primero. El inicializador de campo estático se ejecuta primero. – Prankster

+1

La construcción de A._A ocurre en el constructor estático. Es solo que el compilador lista todas las inicializaciones de campos en el constructor estático (.cctor) antes de que el código se declare en el constructor estático de C#. –

-1

Sí, la inicialización de los campos estáticos debe completarse antes de llamar al constructor. Pero pones el compilador en la situación anormal y simplemente no puede obedecer esta regla.

Esto es un truco interesante, pero no va a suceder en la aplicación normal.

1

De hecho, creo que está haciendo lo que usted piensa. Tu prueba hace que sea difícil de decir.

Su initalization para _A

public static string _A = (new A()).I(); 

Primero crea una nueva instancia de A, por lo tanto, sus escritos de nuevo A() y _A = null. Porque era nulo cuando comenzó, ya que esta es la inicialización. Una vez inicializado, se llama al constructor estático, que devuelve la nueva instancia.

0

Parece que el compilador está haciendo lo esperado.

primero - se ejecuta todo el código estático (campos constructor primero, y luego estática) en la clase:

public static string _A = (new A()).I(); 

// and 

static A() 
{ 
    Console.WriteLine("static A()"); 
} 

segundo - constructor de la clase se llama:

public A() 
{ 
    Console.WriteLine("new A()"); 
    if (_A == null) 
     Console.WriteLine("_A == null"); 
    else 
     Console.WriteLine("_A == " + _A); 
} 

Usted pregunta por qué esto es posible Bueno, en mi opinión, una instancia no requiere absolutamente que todas las variables de clase se inicialicen después de la creación. Solo requiere que deben existir. Creo que este caso particular es compatible con este pensamiento porque se crea una instancia antes de que se realice toda la inicialización estática.

0

Una nota adicional - la especificación de C# (estoy mirando a 4.0, pero está ahí en 3.0 también) dice en 10.5.5.1 Campo estático de inicialización:

Si un constructor estático (§10.12) existe en la clase, la ejecución de los inicializadores de campo estáticos se produce inmediatamente antes de ejecutar el constructor estático . De lo contrario, los inicializadores de campo estáticos se ejecutan en un tiempo dependiente de la implementación antes del primer uso de un campo estático de esa clase.

Usted tiene un constructor estático, por lo que el "otro modo" cláusula no se aplica. Pero creo que es una información relevante para su pregunta saber que si no tiene un constructor estático, los inicializadores de campo estáticos se pueden ejecutar 'en un tiempo dependiente de la implementación'. Esto podría importar si su inicializador de campo estático está realizando algún tipo de inicialización de datos o creación de objetos en los que confíe sin tener que acceder al campo estático en sí.

Creo que es esotérico, pero lo vi hoy ya que el 'tiempo de implementación dependiente' parece haber cambiado entre C# 3.0 y 4.0, al menos para la situación que estaba viendo. La solución fácil, por supuesto, es simple: solo agregue un constructor estático ...

Cuestiones relacionadas