解决构造函数中的虚拟成员调用

Solving virtual member call in constructor

我有一个摘要class:

public abstract class ExampleBase : IExampleBase
{
    protected ExampleBase() 
    {
        this.SetupData();
    }

    protected abstract Dictionary<int, Adress> RelevantData { get; set; }

    protected abstract void SetupData();

    public void ProcessData() 
    {
        // use RelevantData
    }
}

和派生class:

public class Example : ExampleBase
{
    public Example()
    {
    }

    protected override void SetupData()
    {
        this.RelevantData = new Dictionary<int, Adress>
        { 1, new Adress { ... } },
        { 2, new Adress { ... } }
    }
}

在基础 class 中,ReSharper 告诉我

Virtual member call in constructor

我知道由于执行顺序调用该方法很危险..但是我该如何解决这个问题?

上下文: 我想在每个派生 class 中设置数据,然后在基础 class 中处理这些数据。我想在基础 class 中调用 SetupData() 方法,因为它在每个派生的 class.

中都是相同的

派生 class:

基地class:

在 Example(以及所有其他派生的 class)而非 ExampleBase 的构造函数中调用 SetupData,并使 Example 成为密封的 class。

问题是 SetupData 可以访问将由 Example 构造函数初始化的内容。但是只有在 ExampleBase 构造函数完成后才会调用 Example 构造函数。

您的基础 class 构造函数首先被调用。如果您的 subclass 中的重写方法依赖于在其构造函数中完成的任何操作,它将无法工作。就个人而言,我会寻找不同的设计,也许将抽象 class 传递到派生 class 而不是使用继承。

你不知道。你接受这是危险的事实,并且(试图)阻止它。这是一个设计缺陷!

例如,您可以通过将调用移至最高级别 class 或让每个 class 对其自己负责,从而消除方法调用的不安全部分来防止这种情况发生。那么你不需要另一个class(一个基数class)来负责派生classes.

如果那不可能。使用注释或任何其他可用的方法非常清楚地表明开发人员在更新代码时应考虑到此问题。

所以在每个派生中都有几行代码class
如果您需要控制流程顺序,那么您可以这样做

public abstract class MyBase 
{
    public void ProcessData()
    {
        bool processData = true;
    }
    public MyBase()
    {
        bool myBase = true;
    }
    public MyBase(int pass)
    {
        bool myBase = true;
    }
}
public class Example : MyBase
{
    public void GetData() {}
    public Example()
        : base(1)
    {
        bool example = true;
        GetData();
        ProcessData();
    }
}