Duncan Gravill
Duncan Gravill

Reputation: 4682

static class "Initialize" pattern in C#?

What is the benefit of or reason for using this pattern?..

public sealed class myStaticClass
{
    private static bool _initialized;
    private static object _lockObject;

    private static string _someStaticField;
    private static int _anotherStaticField;
    private static string _nthStaticField;

    static myStaticClass()
    {
        _initialized = false;  
        _lockObject = new object();
    }

    public myStaticClass()
    {
    }

    public static void Initialize()
    {
        if(!_initialized)
        {
            lock(_lockObject)
            {
                if(!_initialized)
                {
                    //do initializing
                    _someStaticField = someApplicationSetting;
                    _anotherStaticField = anotherApplicationSetting;
                    _nthStaticField = nthApplicationSetting;

                    _initialized = true;
                }
            }
        }
    }

    public static string NthStaticField 
    { 
        get {

            Initialize();
            return _nthOtherField;
        }
    }
}

If a static constructor is guarenteed to be called before any of the class members are ever accessed and it is only ever called once then why not just put all of the initialization logic in the static constructor?

EDIT: I have updated the pattern to better reflect the class in the .net framework where I have discovered it. I have change the static modifier on the class to sealed and I have also added an empty public constructor.

ps. Incase you would like to know, the class where I have seen this pattern is the FormsAuthentication class.

Upvotes: 7

Views: 5070

Answers (3)

Duncan Gravill
Duncan Gravill

Reputation: 4682

Ok I have now read and considered the links given and have come to the conclusion that this particular example is not broken.

I shall explain why...

Firstly it is not the same pattern as the one in csharpindepth article csharpindepth.com/Articles/General/Singleton.aspx. The pattern in this article is for a singleton. The pattern I have presented is not a singleton, it has a public constructor, however all of it's fields are static. So the big difference is that the csharpindepth pattern returns a reference to a singleton object even though it may not have actually been fully instantiated. The key point is that the instance may be assigned to the reference before the constructor has completed.

public sealed class Singleton
{
 private static Singleton instance = null;
 private static readonly object padlock = new object();

Singleton()
 {
 }

public static Singleton Instance
 {
     get
     {
         if (instance == null)
         {
             lock (padlock)
             {
                 if (instance == null)
                 {
                     instance = new Singleton();
                 }
             }
         }
         return instance;
     }
 }
} 

this is the csharpindepth pattern and it works like this..

If there are 3 threads A, B and C. Thread A calls the Instance method, instance is null, it gets the lock. Now before thread A creates a Sigleton instance along comes thread B, instance is still null. But A has the lock so B waits. While B is waiting thread A executes the code instance = new Instance(). At this point instance is set to an instance of Singleton however it is possible that it has not actually been constructed yet. This is where the thread safety breaks. Along comes thread C, it sees that instance is not null so the Instance method returns a referance to instance. But thread A has not yet finished constructing the instance so Thread C and any other threads that entered at the same time as thread C get a reference to a dud Singleton instance. Finally A finishes, B gets the lock but the work is now done so it exits.

The pattern I have presented is significantly different. The field that is being used for the double check is not an instance that is created in the Initialize method. It is a simple private static bool that is used as a switch. Since it is not a reference to a Singleton object that is yet to be constructed and since it is never accessed outside of this class there is not issue.

There would be an issue if the private static bool _initialized switch was set to true at the top before the class' fields had been initialized but it isn't. It is the last thing to happen before the code gives up the lock. So there is no chance of a thread C reading _initialized and mistaking the class as having been initialized. And so it is not in anyway boken.

Upvotes: 0

torrential coding
torrential coding

Reputation: 1765

Possibly, the ApplicationSettings are not available until later on during run-time.

Upvotes: 1

Yahia
Yahia

Reputation: 70379

The only reason to do so would be if initialization is expensive (in terms of CPU/RAM) OR something needed is only available later during runtime IMO... this implementation delays initialization until the latest possible moment (right before first access). It is kind of what Lazy<T> offers...

Upvotes: 2

Related Questions