20

I would like to know what is the difference between initializing a static member inline as in:

class Foo
{
    private static Bar bar_ = new Bar();
}

or initializing it inside the static constructor as in:

class Foo
{
    static Foo()
    {
        bar_ = new Bar();
    }
    private static Bar bar_;
}
Curro
  • 832
  • 2
  • 10
  • 14

3 Answers3

19

If you have a static constructor in your type, it alters type initialization due to the beforefieldinit flag no longer being applied.

It also affects initialization order - variable initializers are all executed before the static constructor.

That's about it as far as I know though.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 4
    For a concrete example of why it matters: http://stackoverflow.com/questions/217932/whats-the-difference-in-these-ways-of-creating-the-static-instance-for-a-single#218005 – Marc Gravell Oct 20 '08 at 14:06
  • From your link: `The runtime could decide to run the type initializer on loading the assembly to start with`. I assume with generic classes (`class Sample`) the rules change? With compile-time resolution (e.g. C++) the rules would be the same, but .NET does run-time resolution. The runtime won't be instantiating for every possible combination, and I doubt that on loading the assembly it would look ahead to see what types are used. – Nelson Rothermel Nov 07 '12 at 23:11
  • @NelsonRothermel: It initializes the type the first time that constructed type is used - so if you use `Foo` it will initialize that then, and later run the type initializer again if you use `Foo`. – Jon Skeet Nov 07 '12 at 23:15
  • And there is the Code Analysis warning, [CA1810](http://msdn.microsoft.com/en-us/library/ms182275.aspx "Initialize reference type static fields inline"), which recommends inline initializations for performance. "Static constructor checks can decrease performance" it says. – Şafak Gür Apr 13 '13 at 07:58
4

In this case I don't believe there si any practical difference. If you need some logic in initializing the static variables - like if you would want to use different concrete types of an interface given different conditions - you would use the static constructor. Else, the inline initialization is fine in my book.

class Foo
{
    private static IBar _bar;

    static Foo()
    {
        if(something)
        {
            _bar = new BarA();
        }
        else
        {
            _bar = new BarB();
        }
    }
}
Torbjørn
  • 6,423
  • 5
  • 29
  • 42
  • Actually, it can make a big practical difference - see here (the difference was "works" vs "doesn't"): http://stackoverflow.com/questions/217932/whats-the-difference-in-these-ways-of-creating-the-static-instance-for-a-single#218005 – Marc Gravell Oct 20 '08 at 14:05
  • I find the situation described there to be very strange :| Thinking about it, in my singletons I always use two static objects, the actual instance and an object to lock on. The instance I always create in a property method, the lock object I instantiate inline. I never thought about it before. – Torbjørn Oct 20 '08 at 15:04
  • Tobjorn: That sounds like you're usually doing locking when you don't need to then :) (Most of the time I find that the static initialization guarantees are perfectly adequate for singletons.) – Jon Skeet Oct 20 '08 at 15:23
  • That's probably correct. But I find implementing locking always is better than to forget it once when I really need it :| – Torbjørn Oct 21 '08 at 06:34
-1

Twilight zone answer: There is a difference in order of execution between inline initializers and ctor assignment... when you mix in instance and static members and inheritance to boot.

For static members, static initializers 
Static ctors (execute bottom up)
Base static initializer
Base static ctor and so on

For instance members, initializers in current class execute first
Then initializers in base class execute ( up the chain)
Then top-most base ctor is executed (and we walk down now. Instance ctors execute top-down)
Finally current type's ctor is executed.

Example :)

public class CBase
    {
        static Talkative m_Baseob1 = new Talkative("Base Static Initializer-");
        static Talkative m_Baseob2;
        Talkative m_Baseob3 = new Talkative("Base Inst Initializer");
        Talkative m_Baseob4;
        static CBase()
        {
            Console.WriteLine("***MethodBegin: Static Base Ctor");
            m_Baseob2 = new Talkative("Base Static Ctor");
            Console.WriteLine("***MethodEnd: Static Base Ctor");
        }
        public CBase()
        {
            Console.WriteLine("***MethodBegin: Instance Base Ctor");
            m_Baseob4 = new Talkative("Base Instance Ctor");
            Console.WriteLine("***MethodEnd: Instance Base Ctor");
        }
    }
    public class CDerived : CBase
    {
        static Talkative m_ob1 = new Talkative("Derived Static Initializer");
        static Talkative m_ob2;
        Talkative m_ob3 = new Talkative("Derived Inst Initializer");
        Talkative m_ob4;
        static CDerived()
        {
            Console.WriteLine("***MethodBegin: Derived Static Ctor");
            m_ob2 = new Talkative("Derived Static Ctor");
            Console.WriteLine("***MethodEnd: Derived Static Ctor");
        }
        public CDerived()
        {
            Console.WriteLine("***MethodBegin: Derived Instance Ctor");
            m_ob4 = new Talkative("Derived Instance Ctor");
            Console.WriteLine("***MethodEnd: Derived Instance Ctor");
        }
    }
    internal class Talkative
    {
        public Talkative(string sID)
        {
            Console.WriteLine(sID + " - Talkative created" );
        }
    }

    # Main function somewhere
    CDerived s = new CDerived();

Output:

Derived Static Initializer - Talkative created

***MethodBegin: Derived Static Ctor
Derived Static Ctor - Talkative created
***MethodEnd: Derived Static Ctor

Derived Inst Initializer - Talkative created

Base Static Initializer- - Talkative created

***MethodBegin: Static Base Ctor
Base Static Ctor - Talkative created
***MethodEnd: Static Base Ctor

Base Inst Initializer - Talkative created

***MethodBegin: Instance Base Ctor
Base Instance Ctor - Talkative created
***MethodEnd: Instance Base Ctor

***MethodBegin: Derived Instance Ctor
Derived Instance Ctor - Talkative created
***MethodEnd: Derived Instance Ctor 
Gishu
  • 134,492
  • 47
  • 225
  • 308
  • Here the CBase static constructor is only being called because an instance of CDerived is being constructed. If you just call a method in CDerived which doesn't need to touch CBase, the static constructor of CBase won't be called at all. – Jon Skeet Oct 20 '08 at 15:22
  • I'd be surprised if it did.. I mentioned inheritance in the first sentence. My point: Difference in how a variable is initialized based on how (field initializer or in ctor), whether static/inst and whether it is in a type hierarchy. but yeah.. My ans is kinda overkill for the OP's q ;) – Gishu Oct 20 '08 at 16:50