检索时,静态字段未初始化(保持为空)

时间:2017-08-19 12:25:12

标签: c#

我有一个声明如下的类:

public class Eq 
{
    public bool Equals(ValI x, ValI y)
    {
        return nilnul.num.ord.Eq.Singleton.Equals( x , y);
        //throw new NotImplementedException();
    }

    public int GetHashCode(ValI obj)
    {
        return nilnul.num.ord.Eq.Singleton.GetHashCode(obj);
        throw new NotImplementedException();
    }

    static public  Eq Singleton=SingletonByDefault<Eq>.Instance;
}

而SingletonByDefault看起来像:

public class SingletonByDefault<YourClass>
    where YourClass:new()
    //where YourClass:class
{

    static protected  YourClass _Instance= new YourClass();
    static public YourClass Instance
    {
        get
        {
            return _Instance;
        }
    }

    protected SingletonByDefault() {

    }

}

在大多数情况下,当我访问Eq.Singleton成员时,没关系。 但是在某种情况下,我得到了一个空引用异常,它说Eq.Singleton为空。

当我将类Eq的静态“Singleton”字段更改为:

//...
static public Eq Singleton{
    get{
         return SingletonByDefault<Eq>.Instance;
    }
}
//....

异常消失了 - 至少目前是这样。

我怀疑错误是由于静态字段初始化的顺序造成的。现在我的理解是:

1)Eq.Singleton和SingletonByDefault._Instance初始化为null。

2)当我访问Eq.Singleton时,Eq.Singleton初始化为SingletonByDefault.Instance,但是

2.1)从现在开始我访问SingletonByDefault.Instance(然后访问SingletonByDefault._Instance),SingletonByDefault._Instance被初始化为新的Eq()。

3)Eq.Singleton现在将返回“new-ed Eq()”。但

3.1)为什么它是空的?

所以我的理解一定出错了。有人会给我一些启示吗?

1 个答案:

答案 0 :(得分:-1)

微软自己的System.Lazy&lt;&gt; class提供了您需要的单例模式,如下所示。

public static class MySingletons
{
  private static Lazy<Eq> _eq = new Lazy<Eq>( CreateEq );

  private static Eq CreateEq()
  {
    return new Eq();
  }
  static public Eq Eq { get{ return _eq.Value; }} 
}

// usage
var eq = MySingletons.Eq

更新:这是提问者要求的更高级别的通用包装。这消除了一些重复代码,其中单例类支持基本参数较少的构造函数。

public static class MySingletons
{
    static SingletonByLazy<Eq> _eq = new SingletonByLazy<Eq>();

    static public Eq Eq
    {
        get
        {
            return _eq.Singlton;
        }
    }
}
public class SingletonByLazy<T> where T: new()
{
    Lazy<T> _singltonWrapped = new Lazy<T>( CreateSingleton );

    static T CreateSingleton()
    {
        return new T();
    }
    public T Singlton
    {
        get
        {
            return _singltonWrapped.Value;
        }
    }
}