Wednesday, October 04, 2006

.NET Object Construction Sequence


How's a .NET object constructed and what's the order of initialization of object fields & static fields? Let's do a simple test:

class Program
{
static void Main()
{
new SubClass();
Console.Read();
}

class BaseClass
{
Logging baseField = new Logging("BaseClass field initializer");
static Logging baseStaticField = new Logging("BaseClass static field initializer");

static BaseClass()
{
Logging.Write("BaseClass static constructor");
}

public BaseClass()
{
Logging.Write("BaseClass constructor");
}
}
class SubClass : BaseClass
{
Logging subClassield = new Logging("SubClass field initializer");
static Logging subClassStaticField = new Logging("SubClass static field initializer");

static SubClass()
{
Logging.Write("SubClass static constructor");
}

public SubClass()
{
Logging.Write("SubClass constructor");
}
}

class Logging
{
static int count = 1;
public Logging(string info)
{
Write(info);
}

public static void Write(string info)
{
Console.WriteLine("{0}: {1}", count++, info);
}
}
}
Result:

1: SubClass static field initializer
2: SubClass static constructor
3: SubClass field initializer
4: BaseClass static field initializer
5: BaseClass static constructor
6: BaseClass field initializer
7: BaseClass constructor
8: SubClass constructor
The result shows a few interesting things:
1. Derived class field initializer first and base class field initializer next.
2. Class field initializer first and class constructor next.
3. Base class constructor first and derived class constructor next.
4. Static field initializer first and static constructor next.
5. Static constructor first and class constructor next.
5. Derived class static constructor first and base class static constructor next.

What's the reason for such order? Class constructor would reference those fields or static fields thus those fields must be initialized before the class constructor; same as static fields need to be initialized before the static constructor; on the other hand, base class constructor runs before derived class constructor because subclass construction may depend on the the state initialized by the base class, and base class usually has no knowledge about the subclass.

A common mistake is that a class field inialializer is using another non-static field, property or method. For example following code snippet will get compilation error:

public int GetTotalCount()
{
return Service.GetTotalCount();
}

// Compile error: "A field initializer cannot reference the non-static field, method, or property..."
private int _totalNum = GetTotalCount();

// Compile error: "An object reference is required for the non-static field, method, or property..."
static int _totalNum = GetTotalCount();
The easy way to resolve above problem would be making the static GetTotalCount method. You can also initialize the field inside the class constructor if you don't like the static approach.