Home > General > Static fields and the “BeforeFieldInit” flag

Static fields and the “BeforeFieldInit” flag

While upgrading a legacy WinForm application from .NET 2.0 to .NET 4.0, I noticed some slightly different behavior. I’m working with a class that has a private static field and a few static methods.

public class Demo
{
	private static Expensive expensive = new Expensive();

	public static void Start() 
	{
	}

	public static void UseExpensive()
	{
		expensive.DoSomething();
	}
}

internal class Expensive
{
	public Expensive()
	{
		// Expensive operation
	}

	public void DoSomething()
	{
	}
}

The Demo class uses field initialization to create an instance of the Expensive class. The Start method does not use any of the static fields.

The WinForm application calls Demo.Start() in the constructor and Demo.UseExpensive() in a button event.

public partial class SomeForm : Form
{
	public SomeForm()
	{
		InitializeComponent();

		Demo.Start();
	}

	private void button_Click(object sender, EventArgs e)
	{
		Demo.UseExpensive();
	}
}

In .NET 2.0, the constructor of the Expensive class would execute on application start-up. In .NET 4.0 however, the constructor of the Expensive class would not execute until the button event was fired. Since the Expensive class is costly to create due to various operations in the constructor, the button event in .NET 4.0 was noticeably slower on the first click.

The reason is due to how .NET initializes types that contain static fields and/or a static constructor. If a type does not contain a static constructor, it will be marked with the BeforeFieldInit flag.

Using ILSpy to decompile into IL, we can see the current class marked with BeforeFieldInit:

If we include a static constructor (even if it’s empty), we’ll see that the class is no longer marked with BeforeFieldInit:

When marked with BeforeFieldInit in .NET 2.0, static field initialization may occur at any time before a static field is used. This means that static field initialization may occur even if a static field is never used. When marked with BeforeFieldInit in .NET 4.0, static field initialization only occurs before a static field is used. To demonstrate, we can use a console application to see when events occur.

class Program
{
	static void Main(string[] args)
	{
		Console.WriteLine("Started.");
		Demo.Start();
		Console.WriteLine("End.");
	}
}

public class Demo
{
	private static ExpensiveClass expensive = new ExpensiveClass();

	public static void Start()
	{
		Console.WriteLine("In Start method.");
	}

	public static void UseExpensive()
	{
		Console.WriteLine("In UseExpensive method.");
		expensive.DoSomething();
	}
}

internal class ExpensiveClass
{
	public ExpensiveClass()
	{
		Console.WriteLine("In ExpensiveClass constructor.");
	}

	public void DoSomething()
	{
	}
}

The console application is calling Demo.Start() in the Main method, which does not reference any static fields. The output in .NET 2.0 is:

In ExpensiveClass constructor.
Started.
In Start method.
End.

The output in .NET 4.0 is:

Started.
In Start method.
End.

Although the Demo.Start() method never references any static fields, static field initialization occurs anyway in .NET 2.0.

We can force static field initialization to occur in .NET 4.0 by adding a call to Demo.UseExpensive(), which does reference a static field.

static void Main(string[] args)
{
	Console.WriteLine("Started.");
	Demo.Start();
	Demo.UseExpensive();
	Console.WriteLine("End.");
}

The output in .NET 4.0 is:

Started.
In Start method.
In ExpensiveClass constructor.
In UseExpensive method.
End.

As you can see, static field initialization does not occur in .NET 4.0 until a static field is first referenced.

If we update the Demo class and add an empty static constructor, the class will no longer be marked with BeforeFieldInit. If a type isn’t marked with BeforeFieldInit, static field initialization will occur before any class member is used.

class Program
{
	static void Main(string[] args)
	{
		Console.WriteLine("Started.");
		Demo.Start();
		Console.WriteLine("End.");
	}
}

public class Demo
{
	public static ExpensiveClass expensive = new ExpensiveClass();

	static Demo()
	{
	}

	public static void Start()
	{
		Console.WriteLine("In Start method.");
	}

	public static void UseExpensive()
	{
		Console.WriteLine("In UseExpensive method.");
		expensive.DoSomething();
	}
}

The output for .NET 2.0 and .NET 4.0 will be identical:

Started.
In ExpensiveClass constructor.
In Start method.
End.
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: