I would like to get some clarification in regards to how loose the execution timing is for static field initializers in .NET. I'm getting a TypeInitializationException when running the code below in an online compiler(Fiddle), but I get the expected output of 1 in a test console app in VS.
Code:
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);
}
}
Stack trace from online compilation:
[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
What gives? Is it safe to assume that when building under visual studio the code is always guaranteed to work correctly? Thank you for your time.
According to the C# language spec, this is specifically pointed out as an implementation-dependent thing:
The only guarantee you get, is that it must be some time before the first use of a static field.
However, as you probably have found out in your fiddle, adding a static constructor makes this work. A static constructor guarantees that static field initialisers to be run immediately before the static constructor. The good news is that the execution of the static constructor is not implementation-dependent (spec):