【问题标题】:Initialize instance of singleton descendant初始化单例后代的实例
【发布时间】:2016-11-16 04:01:26
【问题描述】:

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

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 构造函数没有。 这可能是因为在类上调用静态方法时会触发静态构造函数。我调用的静态方法是在父级上,而不是在后代上。

【问题讨论】:

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


    【解决方案1】:

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

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

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

    这里有一个例子来证明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" };
        }
    }
    

    【讨论】:

    • > 创建和引用 Derived2 时会发生什么?
    • 我认为你对实例被破坏是正确的,但它确实有效。每个类都创建并持有正确的实例。
    • @BWhite 你确定吗?我刚刚对其进行了测试以仔细检查,它肯定确实被覆盖了。查看我的编辑
    • 考虑到这一行 _instance = new Derived() // in Derived2,这特别有趣
    • @BWhite 抱歉 - 这是一个错字,但将其更改为 new Derived2() 具有相同的效果。我们仍在设置Base._instance
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多