I've read several of the other posts here about this, but my problem seems to fly in the face of the general wisdom posted here (Is the order of static class initialization in C# deterministic?) and several related posts.
I've got an ASP.Net 4.0 application, and my Application_Start() method runs through touching a lot of things to get them set up. One of those things is initializing our db connection string for our DAL, others initializing other variables. A couple of days ago our release builds started blowing up, and after adding a lot of debug logging, the cause turned out to be a new static initizalizer being called before Application_Start() was officially entered and trying to access our DAL before it was initialized. And this seems to run afoul of what I see in other posts here about the order of execution for static constructors and initializers.
Specifically, the static initializers are not being run at the point in the code where they are called; the stack traces in the release build indicate that release compilation shuffles them up to be part of entering Application_Startup(). In other words the stack trace when it blows up shows Application_Startup() on the stack - but no line number associated with it. The stack trace for the DAL initialization does show the line number.
To flesh out some pseudo code, we have
Application_Start()
{
DAL.Inst.GetSetting("ConnectionString"); // tickles the singleton to get the DAL initialized.
// numerous other lines of code
if (!AppUtil.IsAdminAccountSetup)
{ // Do admin account setup
}
// More code
}
public class DAL
{
private static DAL _singleton;
static DAL()
{
_singleton = new DAL();
_singleton.Initialize();
}
public static DAL Inst
{
get { return _singleton; }
}
// all the other methods
}
public class AppUtil
{
private static bool _isAdminSetup = InitializeAdminSetup();
public static bool IsAdminAccountSetup
{
get { return _isAdminSetup; }
}
private static bool InitializeAdminSetup()
{
// Call DAL for query
}
private static bool _isProductRegistered = InitializeProdReg();
public static bool IsProductRegistered
{
get { return _isProductRegistered; }
}
private static bool InitializeProdReg()
{
// Call DAL for query
}
}
AppUtil recently had the IsProductRegistered boolean added, and that seems to be when things headed south.
AppUtil.IsProductRegistered is not called in Application_Start(), but when we look at stack traces about the order of queries to the DAL, we see the initializer for AppUtil.IsProductRegistered calling the DAL (before DAL.Inst gets touched) and from Application_Start() (no line number).
Then we see the connection string getting initialized as part of the DAL static constructor, and that traces back to the DAL.Inst reference in Application_Start() - and here it does show the line number.
If we change both of the static initialzers in AppUtil to a single static constructor, things go back to being initialized in reference order and the blow-up goes away.
But the whole situation flies in the face of what I've read about what .Net says it will do.
Sorry for the information barf, but I hoped to have enough detail to make the conundrum clear.