20-Jun-03 (Created: 20-Jun-03) | More in '00.05-Articles'

How to use static constructors to initialize c# classes, utilities and singletons

Brief summary

Understand some of the issues surrounding static constructors, beforeFieldInit, and static field initialization for effectively using this c# initialization feature.

Quick example of a c# class illustrating the features indicated in this article


public class UtilityClass
{

	//
	// Resources
	//

	// r1 will be initialized by the static constructor
	static Resource1 r1 = null;

	// r2 will be initialized first as static constructors are invoked
	// after the static variables are initialized
	static Resource2 r2 = new Resource2();

	//Notice how there is no public modifier
	//Access modifiers are not allowed on static constructors
	static UtilityClass()
	{
		r1 = new Resource1();
	}

	static void f1(){}
	static void f2(){}
}

Introduction

Resource initialization is a common occurrence in programming. I have seen many libraries in different languages where a developer has to explicitly initialize a facility before starting to use the library. In OO languages this problem is tackled using static variables and constructors that gets called in response to the instantiation of those static variables.

C# while retaining this ability to use static variables for initialization, also provides a language construct called "static constructor". Static Constructors provide a clean way to solve the initialization problems in c# programs.

Let me explore an initialization example to illustrate the various aspects of static constructors. Imagine a case where you are writing a utility class with a set of public static functions. The intention is that other programmers can use these static functions in their programs with out explicitly instantiating the class.


public class UtilityClass
{
	public static void f1(){}
	public static void f2(){}
}

Resources as static variables

If these functions require some resources that need to be acquired at the start and kept for the life of the program, then there needs to be a way to initialize these resources. To demonstrate this case let me add a resource variable called "r1" of type "Resource1" to this UtilityClass. Let us set the resource initially to null while we decide a good way to initialize it. At this stage the modified class will look like this:


public class UtilityClass
{

	//Resources
	static Resource1 r1 = null;

	static void f1(){}
	static void f2(){}
}

Resource initialization using inline instantiation of static objects

One of the ways to initialize this resource to other than null is to directly instantiate the Resource1 inline. The following code demonstrates the common practice of newing classes for static variables inline wherever the static variables are defined.


public class UtilityClass
{

	//Resources
	static Resource1 r1 = new Resource1();

	static void f1(){}
	static void f2(){}
}

This is called static field initialization where field "r1" of type "Resource1" is initialized. We are encouraged to do this because, intuitively we argued with ourselves that this initialization will happen before any of the other static functions are called. So if f1() or f2() is to be called, there is an assumption that "r1" should have been initialized by then. But read on to find otherwise.

beforeFieldInit: The fly in the ointment

There is an exception to this perfect rule. If this class is marked as "beforeFieldInit", then "r1" may not be initialized when the functions are called. According to the CLI "beforeFieldInit specifies that calling static methods of the type does not force the system to initialize the type". This means that the static variables are not initialized just because we called a static function. But CLI does insist that all the field variables will be initialized as soon as one of the static fields is accessed. So if we are depending on some side-affects based on static variable initialization, then we may be waiting for a long time that to happen.

Rational for beforeFieldInit

Why did CLI do this? CLI spec claims that it is expensive to ensure that type initializers are run before a static method is called particularly when executed from multiple application domains. CLI feels that this is OK most of the time. Let me examine this claim in some detail. In the code example above say f1() uses r1 and f2() does not use r1. If f2() is called, it doesn't reference r1 and hence r1 is not initialized. As long as f2() doesn't depend on the initialization of r1 indirectly, this is OK. But what if in the process of instantiating r1 the constructor of Resource1() set up a static hash table in some other class on which f2() depends? As long as these side affects are not going on then the facility of beforeFieldInit is fine.

In other words what they are saying is, if you need a system or module wide initialization, then use a different approach and don't depend on the side affects produced by static variable initialization. So initialization of a class should be a separate language construct rather than being a side affect of field initialization. "static constructor" is one such language construct with initialization semantics.

What about the base classes static variables?

Before covering the static constructors it is worth noting that the CLI specification goes on to warn us about assumptions about base class type initialization. It tells us that don't expect any such initialization to happen automatically. To quote CLI: "Execution of any type's initializer method will not trigger automatic execution of any initializer methods defined by its base type, nor of any interfaces that the type implements"

Static Constructors to the rescue in a couple of ways

Let us modify the above class and initialize "r1" through a static constructor instead. The resulting class will look like the following:


public class UtilityClass
{

	//Resources
	static Resource1 r1 = null;

	static UtilityClass()
	{
		r1 = new Resource1();
	}

	static void f1(){}
	static void f2(){}
}

There is an assurance in the language that this static constructor gets called before any other static method gets called. That means that it is guaranteed that the variables will be initialized before any static function is invoked on that class. Let us look at what the c# documentation says about static constructors:

  • Static constructors are not inherited, and cannot be called directly.
  • The exact timing of static constructor execution is implementation-dependent, but is subject to the following rules:
  • The static constructor for a class executes before any instance of the class is created.
  • The static constructor for a class executes before any of the static members for the class are referenced.
  • The static constructor for a class executes after the static field initializers (if any) for the class.
  • The static constructor for a class executes at most one time during a single program instantiation.
  • The order of execution between two static constructors of two different classes is not specified

To further understand and elaborate on the above rules let us consider the following class definition:


public class UtilityClass
{

	//Resources
	static Resource1 r1 = null;
	static Resource2 r2 = new Resource2();

	static UtilityClass()
	{
		r1 = new Resource1();
	}

	static void f1(){}
	static void f2(){}
}

Static constructor presence trumps BeforeFieldInit

Very, Very interesting. According to the rules resource "r2" gets initialized first, before the static constructor is called and "r1" initialized. Even if r2 is never needed it will still be initialized first. So, defining a static constructor seem to "trump" the "beforeFieldInit". So even if you have an empty static constructor it is guaranteed that static variables will be initialized before any static function gets invoked.

If there is no static constructor then the following rule taken from the c# documentation applies to the initialization of static variables:

"The static field variable initializers of a class correspond to a sequence of assignments that are executed at an implementation-dependent time prior to the static constructor for the class (if any) and prior to the first use of a static field of that class. The static field variable initializers are executed in the textual order in which they appear in the class declaration."

Summarizing the usage of static constructors

It is one thing to open an Oxford English Language dictionary and learn a new word and a completely another thing before the word becomes part of the usage on a daily basis. Programming constructs are no different. These constructs need to be internalized before one can effectively use them. This is how I intend to internalize the static constructors
  • A static constructor looks like a default constructor with 'static' in front
  • It is an error to attach public/private/or protected to a static constructor
  • Presence of a static constructor suppresses BeforeFieldInit
  • static field variables are initialized before the static constructor is called
  • Having a static constructor is the only way to ensure all resources are intialized before other static functions called

When is it OK not to use Static Constructors

If all your static variables can be set up by simply instantiating classes against them, then there is a good chance that you don't need a static constructor. What you have to watch out though is that none of the constructors of these classes have side-effects. For example class1 constructor doing something useful for class2 constructor or the usage of class2 instance. Because, in such a case if class2 variable is to be utilized first then there is no guarantee that class1 constructor would have run. Surprisingly even this won't be a problem if these instances are the static instances of the same class. Because as soon as one of the class instances is utilized everything in that class is initialized.

When do you see the static constructors often?

If a class has a set of static variables that are mainly simple types and not functional classes, then these simple types need to be initialized procedurally as opposed to instantiating them. For example ints, strings, etc, I consider them simple types (although they are classes in their own right). For example a logging class need to remember its log filename, log message levels etc, at start up. Assuming this log class is implemented as a static class, a static constructor will initialize these variables. If you want to do this using static variable initialization, then you need to have a class called LogInitialization whose sole purpose is to initialize this static instance.

Do singletons benefit from static constructors?


public class MySingletonClass
{
	public static MySingletonClass self = new MySingletonClass();
	//Nonstatic MySIngletonClass implementation follow
}

//singletonusage

MySingletonClass.self.doSomething();

The above example shows that majority of singletons don't require static initializers

An alternative to static classes

There is no such language construct called a static class. I tend to refer to a class as a static class when much of its functionality is exposed as a collection of static functions. It is these classes that give rise to static constructors often. It is possible to convert this static class to a regular class and use a singleton of this type instead of the static class that we have started with. There are pros and cons to both approaches. But first let me show examples of both usages.

The static example revisited



//Class definition

public class UtilityClass
{

	//Resoruces
	static Resource1 r1 = null;

	static void f1(){}
	static void f2(){}
}

//Let us see how the above class is used

UtilityClass.f1();
UtilityClass.f2();

In this scenario programmers will directly call the static functions as if they are 'c' like functions. This approach has a lot of simplicity and as a result is usually preferred for utility functions. On the negative side of this approach lies the first assertion that this is not OO programming. Again if it gets the job done and programmers use it with out major drawbacks this is quite reasonable.

static classes as singletons

Let me rewrite the above class as a singleton and show how programmers can use such a facility.



//Class definition

public class SingletonUtilityClass
{
	public static SingletonUtilityClass self = new SingletonUtilityClass();

	//Resources
	Resource1 r1 = null;

	void f1(){}
	void f2(){}
}

//Let us see how the above class is used

SingletonUtilityClass.self.f1();
SingletonUtilityClass.self.f2();

Notice now that the class is a non-static, regular class. Only static variable is the "self" variable pointing to an instance of itself. This is a little bit more verbose than the static version of it. In addition to that you have to ensure the Singleton semantics of it. You should ensure that the constructor of this is private and is not allowed to instantiate from anywhere etc.

Nevertheless there is a reward for going this extra step. In the above example the class is statically bound to the program. If you can utilize a factory that can dynamically instantiate classes and also permits the multiplicity of their instantiations, then you can take the above class and makes it a strategy/factory pattern. Once this happens then you can change your implementation of methods at run time. When properly expanded this method forms the basis of Remoting, COM+ etc.

References