Monday, September 10, 2007

 

Type Initializers, Static Fields and Static Constructors

You probably already know that there are two ways to initialize static variables in C#.NET: in the field declaration, and in the static constructor. You may even think that the following two classes are essentially the same, but they may not be!


/// Initialize via field declaration
class MyClass1
{
static object s_obj = new object();
}

// Initialize via the static constructor
class MyClass2
{
static object s_obj;

static MyClass2()
{
s_obj = new object();
}
}


First of all, let me point out one somewhat obvious point: Creating the instance of type object in the static constructor instead of in the field declaration is good practice because it allows you to insert a try...catch around the instantiation. That could be useful, for example, when loading a string, icon, etc. from a localized resource file; it would allow you to log any exceptions (missing string keys, etc.) that may have been introduced by the localization team. But, this post is about something much more subtle.

Both classes have a type initializer that does the same thing: creates an instance of type object() and assigns it to static variable s_obj. A type initializer is a Common Language Intrastructure (CLI) concept. According the CLI Specification (ECMA 335)


A static constructor, however, is part of the C# Language Specification -- not part of the CLI. According the the C# Language Specification (ECMA 334)


This implies that a C# class cannot be marked as relaxed if it has a static constructor. In C#, all class are unrelaxed by default. You can mark a class as relaxed via the BeforeFieldInit class attribute. You should only mark a class as relaxed if you would like to be able to call certain static or instance methods (those that do not access static fields) without caring whether or not the static type is fully initialized.

Ok, now to put it all together...

In C#.NET, if you declare a static constructor, then you are guaranteed that the static field declarations will be executed before the static constructor, and that the static constructor will be executed before a class is instantiated or any static fields or methods are used.

But, if you do not use a static constructor then initialization of the static fields depends upon whether the class does or does not use the BeforeFieldInit attribute. If the class does not use the attribute, then the static field declarations will be executed before an instance of the class is created or any static members are accessed. However, if BeforeFieldInit is true, then the initialization of the static fields could occur before or after static or instance methods are called -- or even not run at all if no static fields are accessed; you are only guaranteed that the static fields are initialized before any static field is used for the first time.

Comments: Post a Comment





<< Home

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]