in Development

Static Fields

“Types may declare locations that are associated with the type rather than any particular value of the type. Such locations are static fields of the type. As such, static fields declare a location that is shared by all values of the type. Just like non-static (instance) fields, a static field is typed and that type never changes. Static fields are always restricted to a single application domain basis, but they may also be allocated on a per-thread basis.”

The paragraph above is the definition of static field extracted from the CLI specification. The text means that when we create a static field “f” inside a class “C”, the value will not belong to any of the instances we create of C, instead its value is shared across all the instances and therefore “belongs” to the type C itself.

I’ve created a very simple class with one static and two instance fields, which you can see below.

public class BusinessLogic
{
    public int instanceField1;
    public int instanceField2;

    public static int staticField3 = 3;

    public BusinessLogic()
    {
        instanceField1 = 1;
        instanceField2 = 2;
    }
}

I’ve run the code and I’ve created 5 instances of the class above, which we will check with WinDBG. To do it we can execute the next command:

!DumpHeap -type BusinessLogic
Address    MT         Size 
01dfa98c   006668c4   16     
01dfe898   006668c4   16     
01e027a4   006668c4   16     
01e0668c   006668c4   16     
01e13104   006668c4   16     
total 5 objects 
Statistics: 
      MT    Count    TotalSize   Class Name 
006668c4        5           80   BusinessLogic 
Total 5 objects

Once we have the address of the 5 instances we created we can dump the objects one by one by using the command

!DumpObj [Address]

If we take the first object and we use its address one it will display something similar to:

Name: BusinessLogic 
MethodTable: 001c68bc 
EEClass: 00281abc 
Size: 16(0×10) bytes 
Fields: 
MT        Field   Offset  Type          VT  Attr       Value  Name 
6f642b38  4000001      4  System.Int32   1  instance   1      instanceField1 
6f642b38  4000002      8  System.Int32   1  instance   2      instanceField2 
6f642b38  4000003     1c  System.Int32   1  static     3      staticField3

What we have done with this command is to examine the fields of one of the instances in memory of BusinessLogic. We can see that the object has the fields instanceField1, instanceField2 and staticField3 and its values are 1,2 and 3 respectively. So, all is as expected.

Lets focus now on the cool thing of static fields. We can see how “staticField3” is shared across al the instances we create of BusinessLogic by examing the EEClass of the objects. The 5 instances we created before have the same EEClass: “00281abc”. If we examine it with the command

!DumpClass 00281abc

we will see that “staticField3” is present at EEClass level and its value is already initialized.

Class Name: BusinessLogic 
mdToken: 02000002 
Parent Class: 6f3d3ef0 
Module: 001c64f0 
Method Table: 001c68bc 
Vtable Slots: 4 
Total Method Slots: 6 
Class Attributes: 100001  
NumInstanceFields: 2 
NumStaticFields: 1 
      MT  Field    Offset  Type           VT  Attr       Value   Name 
6f642b38  4000001       4  System.Int32   1   instance           instanceField1 
6f642b38  4000002       8  System.Int32   1   instance           instanceField2 
6f642b38  4000003      1c  System.Int32   1   static         3   staticField3

At this point we have demonstrated how the static fields and their values are shared across all the instances we create of a class.

In this sample we have used value types for the static field, but this also applies for reference types. This is very cool, because it allow us creating class designs where objects with a heavy load construction can be instantiated just once  i.e.

static object staticField; 
…. 
if (staticField == null) 
       staticField = new object();

This simple code will allow sharing the same instance of staticField across the entire application domain helping with the performance if staticField is hard to construct.

This does not mean that from now you must create all your “hard to construct” fields as static, because like always the gold hammer does not exist and static fields have a downside.

As we have seen the static field values are related to the EEClass, which are allocated on the loader heaps that are AppDomain specific, so this means they will be in memory until the AppDomain is unloaded.