Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static field initializer runs before Application_start, sometimes

Tags:

asp.net

I've got an ASP.NET web app that is starting to show some very strange behavior. Here's some example code:

// in Bar.cs
public class Bar {
    public static Baz baz = Something.Step2();
}

// in Global.asax
public void Application_Start(...) {
    Something.Step1();
}

The short version of the story is this: On some machines, Something.Step2 is executed before Something.Step1 and is throwing an unhandleable exception. On other machines, Step1 correctly executes before Step2. Global.asax and all the objects it uses do not refer to Bar at all.

When are static fields supposed to execute in relation to other programming elements? Why would two machines (both Win7 64-bit, both with .NET 4.0, same IIS version, etc) execute things in different orders? The order is consistent on each machine too. On my machine, it always executes Step2 before Step1, but on my coworker's machine it always executes Step1 before Step2.

Help very much appreciated.

Update I've found the root cause why my static field is being accessed. Class "Bar" from my example is actually a custom authentication module, and is referenced in web.config as the Authentication handler under System.webServer. If I remove that line from web.config, my system calls Step1 first and never calls Step2 at all. My question changes subtly to: "Why does web.config cause my static initializers to fire, and why does it cause them to fire before Application_Start executes?"

like image 275
Whiteknight Avatar asked Oct 29 '10 15:10

Whiteknight


1 Answers

Static field initializers, when you don't have a static constructor, are initialized at an "implementation-dependent" time prior to the first access. This means that they can be initialized at any time - you can't rely on the initialization of Bar.Baz to occur the first time you use Bar.

Adding a static constructor to Bar will change the behavior of this to be more of what you're expecting.

For details, read the C# language spec, section 10.5.5.1:

10.5.5.1 Static field initialization

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor (§10.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

Also, see 10.2, for details on static constructors:

The static constructor for a closed class type executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

· An instance of the class type is created.

· Any of the static members of the class type are referenced.

That being said, if there is deterministic initialization required, I would strongly recommend adding a static constructor to Something, and doing the initialization properly there. In addition to providing a guarantee of the initialization order in this case, it will prevent usage of Something by another class from causing your code to break in the future.

like image 83
Reed Copsey Avatar answered Sep 20 '22 14:09

Reed Copsey