2009-03-18 8 views
8

Este código tiene el comportamiento bien definido en C# de no trabajar:¿Por qué en C# el pedido es importante para la inicialización estática?

class Foo 
{ 
    static List<int> to = new List<int>(from); // from is still null 
    static IEnumerable<int> from = Something(); 
} 

Nota: No estoy pidiendo cómo solucionar ese código como I already known how to do that

Cuál es la justificación para esto? C# ya realiza comprobaciones de tiempo de ejecución para detectar el primer acceso a miembros estáticos. ¿Por qué no extender esto a cada miembro y hacer que se ejecuten a pedido o incluso mejor que el compilador resuelva el pedido en tiempo de compilación?

BTW: Creo que la misma pregunta (o casi igual) también se aplica a los miembros no estáticos.

+1

Creo que te respondes diciendo que es un "comportamiento bien definido". – mayu

Respuesta

6

puedo imaginar un programador en función de orden de inicialización debido a los efectos secundarios con otra estática clases Usted y yo sabemos que depender de los efectos secundarios es una mala práctica, pero no necesariamente es ilegal.

considerar algo como esto:

class Foo 
{ 
    static string header = Bar.GetHeader(); 
    static string version = Bar.GetVersion(); 
} 

Y Bar.GetVersion supone que Bar.GetHeader ha sido llamado. Si el compilador fuera libre de cambiar el orden de inicialización, entonces el programador no podría garantizar la orden de inicialización.

Feo, concedido, pero perfectamente legal. Si imagina efectos de segundo orden (es decirllamados métodos estáticos que a su vez dependen de clases que tienen efectos secundarios), ves que es imposible para el compilador reordenar de manera confiable cualquier cosa, así como es imposible (en general) que el compilador reordene el orden de las llamadas de función en tu constructor estático.

+0

Un buen punto y podría ser la razón. Dicho esto, creo que la forma de "evaluar en orden" es incorrecta, la forma de resolver eso. Creo que el tacto correcto es decir, "si el orden es importante, inicialícese en un constructor". y "El código que depende del orden de inicialización en línea es ilegal, incluso si se ejecuta". – BCS

1

Creo que lo que necesitas usar es un constructor estático.

Al igual que

class Foo 
{ 
    static List<int> to; 
    static IEnumerable<int> from; 

    static Foo() 
    { 
     from = Something(); 
     to = new List<int>(from); 
    } 
} 

cuanto a por qué C# no lo hace en el primer acceso, sólo que no veo la necesidad de ese tipo de complejidad cuando hay otras alternativas que dejar en claro lo que está sucediendo .

+0

Yo creo que no has leído la pregunta. – Samuel

+0

Leí la pregunta. Preguntar por qué C# hace algo de una manera, nunca va a obtener una respuesta útil. Mi respuesta fue en la línea de, ¿por qué hacerlo cuando puedes hacer esto? – Ray

+0

Preguntar por qué algo funciona en C# ha funcionado muchas veces; solo mira cuánto sabe Jon Skeet sobre la mecánica de C#. – Samuel

1

C# realiza comprobaciones en tiempo de ejecución para detectar el primer acceso a una clase, pero no reordena la inicialización estática dentro de una clase.

Los campos estáticos se inicializan de arriba a abajo seguidos de los constructores estáticos de arriba a abajo. Cambie el orden de sus campos o cree un constructor estático e inicialice los campos desde allí.

Consulte Variable initializers en la especificación C# o this article en los inicializadores. Además, la pregunta Order of static constructors/initializers in C# está relacionada.

+0

Le hice esa pregunta: b También vea mi comentario a Ray. Estoy/no/preguntando cómo arreglar ese código. – BCS

+0

Sí, lo hiciste. :-) ¡Creo que debería prestar más atención! –

+0

"'Algo está mal, por favor, póngase en contacto con el administrador del sistema', Crud! ¡Lo haría pero soy/el administrador del sistema!" BCS

12

Los inicializadores son solo un azúcar sintáctico. El compilador pone ese código en el .cctor cuando compila su clase, y les muestra las órdenes en el código.

No ejecuta ningún control, porque no tendría sentido. Todavía podría tener ciclos de inicialización, por lo que no funcionaría de todos modos.

blogged sobre él hace algún tiempo si está interesado:

+0

Esa es la razón principal: ciclos de inicialización que el compilador no puede resolver. –

+0

Los ciclos siempre son un error: prefiero obtener errores de compilación que los que obtiene actualmente. Aparte de los ciclos, no veo problemas. +1 – BCS

+0

> "El compilador coloca ese código en el .cctor". Sin duda, esto no puede ser correcto. Los inicializadores se invocan en diferente orden que los constructores, ¿verdad? – mayu

Cuestiones relacionadas