C# 避免构造函数中的虚拟调用的一种方法

C# 避免构造函数中的虚拟调用的一种方法,c#,oop,C#,Oop,考虑以下示例中的代码: abstract class Car { public abstract Engine CarEngine { get; protected set; } public Car() { CarEngine.EngineOverheating += new EventHandler(CarEngine_EngineOverheating); } void CarEngine_EngineOverheating(ob

考虑以下示例中的代码:

abstract class Car
{
    public abstract Engine CarEngine { get; protected set; }

    public Car()
    {
        CarEngine.EngineOverheating += new EventHandler(CarEngine_EngineOverheating);
    }

    void CarEngine_EngineOverheating(object sender, EventArgs e)
    {
        // Subscribing to the event of all engines
    }
}

sealed class Toyota : Car
{
    public Toyota()
    {
        this.CarEngine = new ToyotaEngine();
    }


    public override Engine CarEngine { get; protected set; }
}

abstract class Engine
{
    public event EventHandler EngineOverheating;
}

class ToyotaEngine : Engine
{

}
由于CarEngine尚未初始化,此代码无法正常工作。我有什么办法来解决这种情况

我看到的几个选项及其缺点:

  • 手动订阅每个子类-结果是包含大量锅炉板代码,因此容易出错
  • Initialize()函数-容易出错且冗余
  • 我很高兴看到更多的想法


    谢谢

    您可以尝试下面的示例。这会将引擎设置为首次访问

    sealed class Toyota : Car
    {
        public Toyota()
        {
        }
    
        public override Engine CarEngine
        {
            get
            {
                var engine = base.CarEngine;
    
                if (engine == null)
                {
                    engine = new ToyotaEngine();
    
                    base.CarEngine = engine;
                }
    
                return engine;
            }
        }
    }
    

    您不能将Engine对象传递给Car的ctor,然后该ctor将设置属性(可能会使setter私有),并注册事件处理程序吗?

    在Car中创建一个构造函数,将引擎作为参数,并在订阅事件之前分配它,如下所示:

    abstract class Car
    {
        public abstract Engine CarEngine { get; protected set; }
    
        public Car(Engine carEngine)
        {
            CarEngine = carEngine;
            CarEngine.EngineOverheating += new EventHandler(CarEngine_EngineOverheating);
        }
    
        void CarEngine_EngineOverheating(object sender, EventArgs e)
        {
            // Subscribing to the event of all engines 
        }
    }
    
    sealed class Toyota : Car
    {
        public Toyota()
            : base(new ToyotaEngine())
        {
        }
    
    
        public override Engine CarEngine { get; protected set; }
    }
    

    为什么不将引擎绑定到汽车上,然后在引擎的实例化过程中注册EventHandler(如果您需要具有这种设计的EventHandler,也就是说)

    实例化可以如下所示

    new ToyotaEngine(myToyotaCarInstance).
    

    我认为发动机与汽车之间有一个参考是完全正确的。

    我宁愿发动机只通过事件进行通信。必须引用其父对象的子对象使我感到不安:)我认为双向关系是一种方式。让生活变得轻松多了。在您的场景中:没有汽车的发动机会存在吗?还是一辆没有引擎的汽车?这种失去耦合在您的场景中有意义吗?我怀疑,在我看来,这是一个次优的对象模型!而
    Car
    构造函数如何知道它正在创建哪个子类,从而知道它应该使用哪个
    CarEngine
    重写?编译器会为您解决这个问题。因为你说的是
    newtoyota()
    ,它会自动使用
    CarEngine
    。是的,我就是这么做的。谢谢