Me gustaría obtener alguna aclaración con respecto a qué tan flojo es el tiempo de ejecución para los inicializadores de campo estático en .NET. Recibo una TypeInitializationException cuando ejecuto el siguiente código en un compilador en línea ( Fiddle ), pero obtengo el resultado esperado de 1 en una aplicación de consola de prueba en VS.
Código:
using System; using SimpleInjector; public class Program { public static IFactory Factory { get; set; } public interface IFactory { T GetInstance<T>() where T: class; } public class SimpleFactory: IFactory { private readonly Container _container; public SimpleFactory(Container container) { this._container = container; } public T GetInstance<T>() where T : class { return _container.GetInstance<T>(); } } public class Bar { public int Get() { return 1; } } public static class Foo { //static Foo() {} public static readonly int foo = Factory.GetInstance<Bar>().Get(); } public static void Main() { var container = new Container(); var factory = new SimpleFactory(container); container.RegisterInstance(Factory = factory); container.Register<Bar>(); Console.WriteLine(Foo.foo); } }
Seguimiento de la pila de la compilación en línea:
[System.NullReferenceException: Object reference not set to an instance of an object.] at Program.Foo..cctor() :line 22 [System.TypeInitializationException: The type initializer for 'Foo' threw an exception.] at Program.Main() :line 33
¿Lo que da? ¿Es seguro asumir que cuando se construye bajo Visual Studio, siempre se garantiza que el código funcione correctamente? Gracias por tu tiempo.
De acuerdo con la especificación del lenguaje C# , esto se señala específicamente como algo que depende de la implementación:
Si existe un constructor estático en la clase, la ejecución de los inicializadores de campo estático ocurre inmediatamente antes de ejecutar ese constructor estático. De lo contrario, los inicializadores de campos estáticos se ejecutan en un momento dependiente de la implementación antes del primer uso de un campo estático de esa clase.
La única garantía que obtiene es que debe pasar algún tiempo antes del primer uso de un campo estático.
Sin embargo, como probablemente haya descubierto en su violín, agregar un constructor estático hace que esto funcione. Un constructor estático garantiza que los inicializadores de campos estáticos se ejecuten inmediatamente antes que el constructor estático. La buena noticia es que la ejecución del constructor estático no depende de la implementación ( spec ):
La ejecución de un constructor estático se desencadena por el primero de los siguientes eventos que ocurren dentro de un dominio de aplicación:
- Se crea una instancia del tipo de clase.
- Se hace referencia a cualquiera de los miembros estáticos del tipo de clase.