The first time I received the “Do not declare explicit static constructors” message from FxCop I was a bit dismayed. Why is it telling me there is a performance penalty for a static constructor? One caveat I’ve always had with FxCop is that the tool enforces design guidelines for a framework, and these guidelines are not necessarily the same guidelines you’d want for an application. To get to the bottom of the critical warning message about static constructors required some research.
The key is a metadata flag the compiler adds to a class without an explicit static constructor – the beforefieldinit flag. In the code below, both Foo and Bar should appear identical in their behavior, and really they are almost identical if you look at both with a decompiler. The difference is, Foo will have the beforefieldinit flag, and Bar will not.
class Foo { public static string Message { get { return _message; } } static string _message = "Hello World!"; } class Bar { static Bar() { _message = "Hello World!"; } public static string Message { get { return _message; } } static string _message; }’
Brad Abrams has some details about beforefieldinit in his blog post from earlier this year. However, after doing some experiments I’d give a slightly different description about the effects of beforefieldinit.
The beforefieldinit flag allows the runtime to be very ‘eager’ in calling a static constructor, a.k.a a type initializer. This is in contrast to being lazy and calling the static constructor at the last possible moment (in hopes you might not need to call it at all). The difference between eagerness and laziness can be demonstrated by timing the following code using Foo and then Bar.
for(int i = 0; i < Int32.MaxValue - 1; i++) { string s = Foo.Message; }
In my experiments, looping with Bar (explicit static constructor) will perform about 5x slower than looping with Foo (implicit static constructor and beforefieldinit set). With Bar in the loop, the runtime must invoke the static constructor at the last possible moment (the spec says it), so the check to see if the type constructor needs invoked is inside the loop. With Foo and the beforefieldinit flag, the runtime is free to eagerly execute the static constructor before the loop starts and thus avoid the overhead of further checks.
Obviously I’ve created a worst case scenario to see the possible performance impact, and performance should not always dictate design decisions. Still, I’m a little disappointed that my beloved static constructors feel a little bit tainted now.