C#中的静态类“初始化”模式?

时间:2012-03-16 22:12:46

标签: c# static initialization

使用此模式的好处或原因是什么?..

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

如果静态构造函数在任何类成员被访问之前被调用并且只被调用一次,那么为什么不将所有初始化逻辑放在静态构造函数中呢?

编辑:我更新了模式以更好地反映我发现它的.net框架中的类。我已将类的static修饰符更改为sealed,并且还添加了一个空的public构造函数。

PS。如果您想知道,我见过这种模式的类是FormsAuthentication类。

3 个答案:

答案 0 :(得分:2)

这样做的唯一原因是初始化是昂贵的(就CPU / RAM而言)或者所需的东西只能在运行时IMO之后才能使用...这种实现将初始化延迟到最新的可能时刻(在第一次访问之前) )。这是Lazy<T>提供的......

答案 1 :(得分:1)

可能,ApplicationSettings在运行期之后才可用。

答案 2 :(得分:0)

好的,我现在已阅读并考虑了给出的链接,并得出结论此特定示例未被破坏。

我将解释原因......

首先,它与csharpindepth文章csharpindepth.com/Articles/General/Singleton.aspx中的模式不同。本文中的模式适用于单例。我提出的模式不是单例,它有一个公共构造函数,但它的所有字段都是静态的。因此,最大的区别是csharpindepth模式返回对单例对象的引用,即使它实际上可能没有完全实例化。关键点是可以在构造函数完成之前将实例分配给引用。

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

这是csharpindepth模式,它的工作原理如下..

如果有3个线程A,B和C.线程A调用Instance方法,实例为null,它获取锁定。现在,在线程A沿着线程B创建一个Sigleton实例之前,实例仍然是null。但A有锁,所以B等待。当B在等待时,线程A执行代码instance = new Instance()。此时,实例被设置为Singleton的实例,但是它可能尚未实际构建。 这是线程安全性中断的地方。沿着线程C,它看到实例不为null,因此Instance方法返回实例的referance。 但是线程A尚未完成构造实例,因此Thread C和与线程C同时进入的任何其他线程都获得对dud Singleton实例的引用。最后A完成,B获得锁定,但现在已完成工作,因此退出。

我提供的模式有很大不同。用于双重检查的字段不是在Initialize方法中创建的实例。它是一个简单的private static bool,用作开关。因为它不是对尚未构造的Singleton对象的引用,并且因为它永远不会在此类之外访问,所以没有问题。

如果在初始化类字段之前将private static bool _initialized开关设置为true,则会出现问题,但事实并非如此。这是在代码放弃锁之前发生的最后一件事。因此,线程C没有机会读取_initialized并将该类误认为已经初始化。所以它不会被诅咒。