BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

C# Programming
.NET 1.1+

C# Static Field Initialisation Order

Static fields can be used to hold information that is made available by, or used within, a class without requiring that an instance of that type is created. When initialising static fields, care must be taken that values are applied in the correct order.

Static Fields

Fields can be declared as static in the same manner as methods and properties. The addition of the static keyword indicates that a field is accessed using its class name, rather than via an instance of the class. If a static field is private, it's value may only be read and manipulated from within instances of its containing type and only one value is maintained and shared between those instances. If the field has a wider scope, all types that have access to it see the same value.

When you create a class that contains static fields, it is important that you initialize them in the correct order. Consider the following code:

class AttemptController
{
    internal static int Threshold = MaxAttempts - WarningAttempts;
    internal static int MaxAttempts = 5;
    internal static int WarningAttempts = 2;
}

The above code seems OK at first glance. The MaxAttempts value is set to 5, the WarningAttempts field to 2 and the Threshold value to the difference of the other two fields. You might expect the Threshold value to be 3. However, if you run the following code to output the values, you will see results that you may not expect:

Console.WriteLine("Maximum:   {0}", AttemptController.MaxAttempts);
Console.WriteLine("Warning:   {0}", AttemptController.WarningAttempts);
Console.WriteLine("Threshold: {0}", AttemptController.Threshold);

/* OUTPUT

Maximum:   5
Warning:   2
Threshold: 0

*/

As you can see in the comment, it appears that the Threshold field's value is being incorrectly calculated.

C# Specification

The cause of the unexpected value can be found in the C# Language Specification. This is the definitive documentation for C# syntax and usage. The document specifies that static fields can never be seen as uninitialised values. If they are accessed before a value has been applied, the default value for their data type is returned. For integer values, this is zero. The C# Language Specification also tells us that when static fields are initialised by applying a value in their declaration, as we have done above, they are set in the order in which they appear in the code. This means that when the Threshold value is calculated, we are using two uninitialised values, each of which yields a result of zero. The Threshold field's calculation is therefore the result of zero minus zero, which is zero.

A simple fix is to reorder the declarations to ensure that the MaxAttempts and WarningAttempts values are present before they are needed, as shown below:

class AttemptController
{
    internal static int MaxAttempts = 5;
    internal static int WarningAttempts = 2;
    internal static int Threshold = MaxAttempts - WarningAttempts;
}

Running the program now gives the correct results:

Maximum:   5
Warning:   2
Threshold: 3

Unfortunately, this approach does not generate the most readable and maintainable code. It is quite possible that another developer may change the order of the fields at a later time, perhaps to sort them alphabetically, unwittingly introducing a bug. A better fix is to remove the initialisation from the field declarations and instead set the values within a static constructor, as shown below:

class AttemptController
{
    internal static int MaxAttempts;
    internal static int WarningAttempts;
    internal static int Threshold;

    static AttemptController()
    {
        MaxAttempts = 5;
        WarningAttempts = 2;
        Threshold = MaxAttempts - WarningAttempts;
    }
}
8 January 2012