views:

3993

answers:

3

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_;
}
+3  A: 

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
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
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
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
That's probably correct. But I find implementing locking always is better than to forget it once when I really need it :|
Torbjørn
+11  A: 

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
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
A: 

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
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
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