初始化单例后代的实例

时间:2016-11-16 04:01:27

标签: c# inheritance static-constructor object-initialization

在传统的单例中,您可以像这样初始化实例:

private static readonly Messages _instance = new Messages();

然后你通过一个getter访问它,就像这样:

    public static Messages Instance {
        get {
            return _instance;
        }
    }

在这种情况下,我们有一个父亲和多个后代。

我们有父母

    protected static Base _instance;
    public static Base Instance {
        get {
            return _instance;
        }
    }

在后代中,我们使用类构造函数来填充静态变量。

    static Derived() {
        _instance = new Derived();
    }

这应该有效,因为在使用它之前首次引用类时会调用类构造函数。 出于某种原因,这不起作用。

   Derived.Instance.Initialize();

失败,因为Instance为null并且构造函数中的断点永远不会被命中。

更新:调用Base构造函数,但Derived构造函数不会调用。 这可能是因为在类上调用静态方法时会触发静态构造函数。我调用的静态方法是父节点,而不是后代。

2 个答案:

答案 0 :(得分:1)

它没有执行Derived构造函数,因为即使您编写Derived.Instance,C#也很聪明,并且意识到Instance实际上是在Base上定义的 - 并将调用重新写为Base.Instance.Initialize(),因此它不会初始化Derived

无论如何,这似乎是一个非常糟糕的主意。创建和引用同时设置实例的Derived2时会发生什么?现在你已经走了,并且被摧毁了Derived.Instance

在不知道为什么这样做的情况下,解决方法是在Derived上定义静态成员,该成员在Derived.Instance之前在外部引用,或者创建new static Derived InstanceDerived

以下示例说明Dervied2将覆盖该实例:

void Main()
{
    //Prints null
    Console.WriteLine(Derived.Instance?.Name);

    //Prints Derived
    var a = Derived.InitDerived;
    Console.WriteLine(Derived.Instance?.Name);

    //Prints Derived2
    var b = Derived2.InitDerived;
    Console.WriteLine(Derived.Instance?.Name);
}

public class Base
{
    public string Name { get; set; }
    protected static Base _instance;
    public static Base Instance
    {
        get
        {
            return _instance;
        }
    }
}
public class Derived : Base
{
    public static int InitDerived = 1;
    static Derived()
    {
        _instance = new Derived() { Name = "Derived" };
    }
}

public class Derived2 : Base
{
    public static int InitDerived = 2;
    static Derived2()
    {
        _instance = new Derived()  { Name = "Derived2" };
    }
}

答案 1 :(得分:0)

  

我正在调用的静态方法是父项,而不是后代。

这就是问题所在。调用了基类的类构造函数,因为调用了属于父类的静态方法。

在子代上调用静态方法之前,不会调用后代类构造函数。

Derived1.EmptyStaticMethod(); //This provokes the class constructor
Derived2.EmptyStaticMethod();
Derived1.Instance.Initialize(); // This now works.