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尚未初始化,此代码无法正常工作。我有什么办法来解决这种情况
我看到的几个选项及其缺点:
谢谢 您可以尝试下面的示例。这会将引擎设置为首次访问
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
。是的,我就是这么做的。谢谢