C# Static Constructor

Dot Net Perls

What is the performance hit for static constructors in your C# programs? Microsoft's documentation and many developers warn that static constructors on a type impose a substantial overhead. Static constructors, which are also called type initializers, can be used to initialize fields before they are accessed.

Conceptual graphic

Example

We see an example class with a static constructor, and also an example class without. Most classes you use will likely not have static constructors. My results were that static constructors do cause a slowdown of all accesses to the type. Note that instances are not the same as types, in that instances are specific objects of the type.

Program that demonstrates static constructor [C#]

/// <summary>
/// This type has a static constructor.
/// </summary>
static class HasStaticConstructor
{
    /// <summary>
    /// Public field.
    /// </summary>
    public static int _test;

    /// <summary>
    /// Static constructor initializes public field.
    /// </summary>
    static HasStaticConstructor()
    {
	_test = 1;
    }
}

/// <summary>
/// This type has no static constructor.
/// </summary>
static class NoStaticConstructor
{
    /// <summary>
    /// Public field initialized inline.
    /// </summary>
    public static int _test = 1;
}

class Program
{
    static void Main()
    {
	System.Console.WriteLine(HasStaticConstructor._test);
	System.Console.WriteLine(NoStaticConstructor._test);
    }
}

Output

1
1

Benchmark notes

The value 2 is stored in the _test field in each iteration.

Benchmark results

HasStaticConstructor: 2.89 ns
NoStaticConstructor:  0.32 ns

Description. What the code does is compare a class that has a static, type constructor against one that does not. In the first class, which has the static constructor, the static field _test is initialized in the constructor.

Class without static constructor. In the second class, which has no static constructor, the _test field is initialized inline, meaning directly in the declaration. This has the same effect on behavior.

Performance optimization

Note: It is possible to have code that accesses a field in class with a static constructor that has no performance penalty. This seems to depend on how early in the program the field is first accessed. It is nevertheless best to avoid static constructors for maximum performance. Bogdan Potor wrote in with a benchmark.

Summary

We saw that static constructors might be convenient, but that they are slow. The runtime is not smart enough to optimize them in the same way it can optimize inline assignments. It is appropriate to use a lazy instantiation pattern sometimes, meaning you check a field for null in an accessor each time it is accessed, and if it is null, you can initialize it.

Static Modifier