在C#基构造之前执行派生构造
-
09-09-2019 - |
题
在这里,我的问题是,我想将一个对象传递给一个派生类,但它必须与基类的构造函数之前完成,因为基类会立即调用使用该对象的派生类的Start()
方法。
下面是从基类的摘录,(从 BarcodeScanner 重命名一>为方便起见)。
public abstract class MyBase
{
public MyBase()
{
if (Initialize())
this.Start();
}
public abstract bool Initialize();
public abstract void Start();
}
下面是我要创建的派生类。
class MyDerived : MyBase
{
private string sampleObject;
public MyDerived (string initObject)
{
sampleObject = initObject;
}
public override bool Initialize()
{
return GetDevice();
}
public override void Start()
{
Console.WriteLine("Processing " + sampleObject.ToString());
}
}
我怀疑就可以使C#执行基构造之前派生构造;所以我确实只是寻找的溶液中使用的对象之前的对象传递到派生的类。
我已经把初始化/启动,如果块MyDerived
构造函数中解决此得到。但是,也有其他类从基类派生;所以我最后不得不重复的初始化/启动代码块中每一个派生类。我希望看到的替代修改的基类。
解决方案
你所要做的是在C#中是不可能的。之前的任何派生类的构造函数,否则就不会有腐败对象状态的潜力在基类的构造函数必须运行。子对象必须能够假定其基部被完全构造和使用。
其他提示
恕我直言,你的设计是错误的。你不应该在构造函数中启动进程。当需要时你消费代码应明确调用Start()方法。
我要返工你的设计,使初始化(和潜在的start() - 虽然我通常有这样的是已被用户调用的公共方法)施工后称为
。如果你正在做一个BarcodeScanner,你可以这样做你第一次去扫描。只是使用从派生的类的数据懒惰初始化您的成员。
这将解决您的问题,从用户的使用情况没有实质性改变。
对不起用于添加到一个古老的线程,但也许有人有兴趣的另一种回答。我发现一个(IMO)整洁的方式来处理逻辑做的东西比(后)多在类的构造函数只是分配领域那里继承参与这里。 如果你只是想如果有这个特定层次结构,而不是使用同一个接口和一个扩展方法的通用的解决方案,你可以使用相同的概念,在一个分类是这样的:
public abstract class MyBase
{
protected MyBase()
{
if (Initialize(this)) // just to illustrate; this will never pass here as this class is abstract
this.Start();
}
protected bool IsInitialized { get; private set; } = false;
protected static bool Initialize<T>(T instance) where T: MyBase
{
if (instance?.GetType() == typeof(T)) // check if this is called from the constructor of instance run time type
return instance.IsInitialized || ( instance.IsInitialized = instance.Initialize() );
return false;
}
protected abstract bool Initialize();
public abstract void Start();
}
和衍生的:
class MyDerived : MyBase
{
private string sampleObject;
protected bool started = false;
public MyDerived (string initObject)
{
sampleObject = initObject;
if (Initialize(this)) // if this is the most derived constructor, this will run Initialize() and return whether it was successful
this.Start();
}
protected override bool Initialize()
{
return GetDevice();
}
public override void Start()
{
// if Start() would be protected, we don't need the IsInitialized property and we can move this check to the constructor on the returned value of the Initialize<T>() call.
if (!IsInitialized) throw new InvalidOperationException("Initialization failed.");
// if you want to have this method exposed public, we need to check if this instance is successfully initialized from the constructor and not in started state already.
if (started) return;
Console.WriteLine("Processing " + sampleObject.ToString());
started = true;
if (!Run(sampleObject)) started = false;
}
}
不隶属于 StackOverflow