What is the best way to declare static fields?

Today I wrote a simple application, which shows what the difference is between initializing a static field in the explicit static constructor and doing the same during the declaration time (inline). I know that even when we initialize our static fields inline, the compiler will add an implicit static constructor to that class and initialize static values in that method. But this example showed me that there is really a long time difference between initializing static fields inline and in explicit static constructor. Here are a screenshot from the example - in this example BeforeFieldInit means that the static fields are initialized inline and NotBeforeFieldInit means that static fields are initialized in the explicit static constructor:

Screen Capturing Example

Download Example Code

Declaring a static field and initializing its value in an explicit static constructor.

using System;

namespace
BeforeFieldInitExample
{
    public class
NotBeforeFieldInit
    {
        // here there is only decleration of the static field
        public static int
A;

        static
NotBeforeFieldInit()
        {
            // Initialization of A's values is here in the explicit static constructor
            A = 0;
        }
    }
}


Initializing a static fields value during the decleration (inline).

using System;

namespace
BeforeFieldInitExample
{
    public class
BeforeFieldInit
    {
        public static int
A = 0;
    }
}


These two code groups will work as the same and produce the same result. Actually when we compile the second code, the output will be as the same with the first code. I mean, during the compiling time the compiler will create an implicit static constructor for the BeforeFieldInit class and initialize the field's value in that method. So it will be the same with the first code.

But there is a small difference between these codes. The difference can only be seen by checking the IL codes of these types.

For the first example, IL code of the class NotBeforeFieldInit will be as follows:

.class public auto ansi NotBeforeFieldInitClass
            extends
object
{
    .
method public hidebysig specialname
            rtspecialname instance
            void .ctor() cil managed
    {
        // Code Size: 7 byte(s)
        .maxstack
8
        L_0000: ldarg.0
        L_0001: call instance
void object::.ctor()
        L_0006: ret
    }

    .
method private hidebysig specialname
            rtspecialname static
            void .cctor() cil managed
    {
        // Code Size: 22 byte(s)
        .maxstack
8
        L_0000: nop
        L_0001: ldc.i4.0
        L_0002: stsfld int32 BeforeFieldInitExample.NotBeforeFieldInitClass::A
        L_0007: ldc.r8 9
        L_0010: stsfld float64 BeforeFieldInitExample.NotBeforeFieldInitClass::B
        L_0015: ret
    }

    .field public static
int32 A
    .
field public static
float64 B
}


And for the second example, which the name of the class is BeforeFieldInit's IL code will be as runs:
.class public auto ansi
            beforefieldinit // here beforefieldinit mask is added
                BeforeFieldInitClass

        extends object
{
    .
method public hidebysig specialname
            rtspecialname instance
            void .ctor() cil managed
    {
       // Code Size: 7 byte(s)
        .maxstack
8
        L_0000: ldarg.0
        L_0001: call instance
void object::.ctor()
        L_0006: ret

    }

    .method private hidebysig specialname
            rtspecialname static
            void .cctor() cil managed
    {
        // Code Size: 21 byte(s)
        .maxstack
8
        L_0000: ldc.i4.0
        L_0001: stsfld int32 BeforeFieldInitExample.BeforeFieldInitClass::A
        L_0006: ldc.r8 9
        L_000f: stsfld float64 BeforeFieldInitExample.BeforeFieldInitClass::B
        L_0014: ret

     }

    .field public static int32 A
    .
field public static
float64 B
}

IL codes generated by Xenocode Fox 2007

As you see in the IL the only difference between these two codes is the second class's having the beforefieldinit flag. So what is this flag doing?

beforefieldinit flag tells to the JIT that this class's static fields are initialized inline. If a class has no beforefieldinit flag, then JIT compiler will automatically check whether explicit static constructor is called before. This means that whenever you want to try to access any static member of this class or try to create a new instance of this class, JIT will automatically calls the explicit static constructor. Therefore you will loose performance because whenever you try to access a static member, JIT also checks whether static constructor is invoked before. But in the second example if we add a beforefieldinit flag to our class, this means that our static members are initialized inline, so JIT does not need to check whether static constructor is invoked before. This is the main reason that causes performance difference between those two classes. When we wrote an explicit static constructor and initialize our fields' values, the compiler will not add beforefieldinit flag to that class. But if we initialize our static fields inline, then compiler will add an implicit static constructor and initialize our static fields there and also add the beforefieldinit flag to our class.

So always, try to use inline field initialization for the static fields if you can.

Related posts

Comments

August 20. 2008 08:58 PM

I've tried it but I got different results !

In debug mode I get :
NotBeforeFieldInit: 115 ms
NotBeforeFieldInit: 114 ms
NotBeforeFieldInit: 117 ms
NotBeforeFieldInit: 115 ms
BeforeFieldInit: 47 ms
BeforeFieldInit: 45 ms
BeforeFieldInit: 47 ms
BeforeFieldInit: 46 ms


But When & run the release version outside VS.Net, I get :
NotBeforeFieldInit: 63 ms
NotBeforeFieldInit: 63 ms
NotBeforeFieldInit: 64 ms
NotBeforeFieldInit: 63 ms
BeforeFieldInit: 92 ms
BeforeFieldInit: 92 ms
BeforeFieldInit: 92 ms
BeforeFieldInit: 97 ms

Any idea about what's happening on?

gheribil
August 21. 2008 07:53 AM

Interesting,

Here is my results (Outside VS, in release mode)

NotBeforeFieldInit: 44 ms
NotBeforeFieldInit: 43 ms
NotBeforeFieldInit: 43 ms
BeforeFieldInit: 13 ms
BeforeFieldInit: 13 ms
BeforeFieldInit: 13 ms

Ozcan DEGIRMENCI
October 21. 2008 04:38 PM

inline initialization is good for fundamental types, but sometimes it's not good for complex or user defined types. Because, we may encounter some initialization errors (because of bugs etc.) that the debugger may not check. (especially, when developing windows forms)
Burak
October 21. 2008 05:46 PM

I didn't care about the initialization errors while writing this article. Also I also don't understand that why the debugger will check initialization errors? It is CLR's responsibility to manage errors not the debugger's. Anyway what I try to said in my article is;

If we don't initialize our static fields during declaration then CLR will always check that is this class's static fields initialized or not whenever we try to access any member on that class. So this will have a performance cost.

Of course it is not possible to initialize all static fields during the declaration, we may need some arguments of we may do some specific operations before initialization. This is why I said that "Try to use inline initialization if you can." even they are complex types.

Ozcan DEGIRMENCI
December 25. 2008 04:43 PM

You do a great job Smile a compiler and ide on a symbian device is awesome!
Busby SEO Test Pinay
January 20. 2009 06:17 AM

compile is a set of program.,..thanks for sharing your post and ideas i admire it !!i just want to say thank you very much!
Busby SEO Test
January 20. 2009 08:04 AM

You're welcome
Ozcan DEGIRMENCI
February 3. 2009 12:30 PM

nice and good article..
i love reading this.. bookmarked !!

Inventory Management Software
February 19. 2009 06:27 PM

Nice post and thanks for the example code as well. Good to see people going that bit extra...
Stonehenge Tours
February 24. 2009 10:24 AM

Interesting post.. thanks for the example code.. you make me must try to understand this code.. Smile
Inventory Management Software System
March 9. 2009 09:41 PM

This is a great description for declaring static fields. thank you for making it easy to understand.
san francisco business partnership lawyers
April 22. 2009 12:16 PM

compile is a set of program.,..thanks for sharing your post and ideas i admire it !!i just want to say thank you very much!
Melayu Boleh
June 10. 2009 01:27 AM

I understand now.
I should always try to use inline field initialization for the static fields.

susunan kabinet 2009
June 26. 2009 02:26 PM

I think you make a good point. Thanks for taking the time to share this with us, i am always searching for informative information like this

Tukang Nggame
July 3. 2009 01:18 AM

One more question, is - how compiler makes sure that static fields with BeforeFieldInit are initialized.
I have some "strange" results when declaring static property in both classes and use these Properties instead static fields in your test - The timings are allways equals (VS and standalone).
I think this proves my assumption that static constructor call verification performed in both cases (with or without BeforeFieldInit), but when BeforeFieldInit is present this verification performed at the method start, not at each static member access.

Alexander
July 3. 2009 10:36 AM

Here what the MSDN says;

BeforeFieldInit: Specifies that calling static methods of the type does not force the system to initialize the type.

Ozcan DEGIRMENCI

Add comment


 

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

July 4. 2009 06:45 PM


Search

Calendar

<<  July 2009  >>
MonTueWedThuFriSatSun
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
View posts in large calendar

Disclaimer

© 2007 - 2008
Ozcan DEGIRMENCI
All rights reserved. The content can be used elsewhere given that the source is properly acknowledged.