2010-04-13 13 views
5

Dado el siguiente código, ¿por qué no se llama al constructor estático de "Exterior" después de la primera línea de "Principal"?¿Por qué no se llama al constructor estático de la clase primaria cuando se invoca un método en una clase anidada?

namespace StaticTester 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Outer.Inner.Go(); 
      Console.WriteLine(); 

      Outer.Go(); 

      Console.ReadLine(); 
     } 
    } 

    public static partial class Outer 
    { 
     static Outer() 
     { 
      Console.Write("In Outer's static constructor\n"); 
     } 

     public static void Go() 
     { 
      Console.Write("Outer Go\n"); 
     } 

     public static class Inner 
     { 
      static Inner() 
      { 
       Console.Write("In Inner's static constructor\n"); 
      } 

      public static void Go() 
      { 
       Console.Write("Inner Go\n"); 
      } 
     } 
    } 
} 

Respuesta

5

En el caso de las clases anidadas, si la clase anidada nunca hace referencia a los miembros estáticos de su ámbito externo, el compilador (y CLR) no necesitan llamar al constructor estático de esa clase externa.

Si desea forzar la ejecución del constructor estático, simplemente agregue el código al tipo interno que realiza una lectura de un campo o propiedad del tipo externo.

Puede leer más sobre la semántica de inicialización perezosa de C# en Jon Skeet's blog - es bastante bueno. También puede consultar su libro: C# In Depth, que cubre estos temas también ... en profundidad.

+0

Es gracioso, saqué mi copia de C# In Depth para ayudar a descubrir por qué. –

3

Outer.Inner se refiere solamente a un tipo, en realidad no es nada invocando el "exterior".

+0

He puesto esto aquí para que los demás no reflexionen sobre esto durante todo el tiempo que lo hice. –

0

Un inicializador estático solo se ejecuta cuando la clase que lo contiene se utiliza por primera vez.

Llamando Outer.Inner, que no está utilizando Outer en absoluto, ya Outer.Inner es un tipo diferente de Outer. Por lo tanto, no se ejecutará el inicializador estático en Outer.

+0

Ah, no vi tu comentario allí :) –

6

Su pregunta es contestada por el artículo 10.12 de la especificación, que establece:

La ejecución de un constructor estático se desencadena por la primera de las siguientes eventos que ocurran dentro de un dominio aplicación:

• Una instancia de se crea el tipo de clase.

• Cualquiera de se hace referencia a los miembros estáticos del tipo de clase .

Como no ha hecho ninguna de estas dos cosas, no se ejecuta el ctor.

+0

¿Pero 'Inner' no es miembro de' Outer'? Y 'Inner' está referenciado. Seguramente 'Inner' no es una instancia membr? Entonces, ¿no es un miembro estático? ¿Quizás las clases anidadas no deben considerarse miembros a este respecto? –

+0

@JeppeStigNielsen: Haces un buen punto; Yo era impreciso Debería haber dicho cualquiera de los campos * static, métodos, propiedades, eventos, indizadores u operadores *. –

+0

Usted citó la especificación con precisión. ¿De verdad estás diciendo que la especificación es imprecisa (o tal vez estás diciendo que escribiste esta parte de la especificación)? O tal vez los tipos anidados no deben considerarse miembros en este contexto. –

Cuestiones relacionadas