稍后用循环引用初始化对象套用 NullReferenceException

Initializing objects with circular references casing NullReferenceException later

无论如何,我的代码是这样的:

        SystemOutput systemOutput = null;
        SystemCL system = null;
        WindowsForm wf = null;

        wf = new WindowsForm(system);
        systemOutput = new SystemOutput(wf);
        system = new SystemCL(systemOutput, wf);

其余代码对于解决我的问题并不重要(我认为?)

所以你可以看到对象相互引用,这意味着如果其他对象还没有被初始化,它会给我一个错误。所以我首先尝试使它们为空,但现在第一个对象获得一个空引用指针,因为该对象为空。

我该如何解决这个难题?有更好的方法吗?

注意What is a NullReferenceException, and how do I fix it?不包括这种情况。

答案是一开始就不要创建拼图。不要创建循环引用,比如 WindowsForm 依赖于 SystemCLSystemOutput 依赖于 WindowsForm,然后 SystemCL 依赖于它们。

不要将如何使这些 classes 按照设计的方式工作视为一个难题。难题在于如何以不同方式设计它们,以便它们不会以这种方式相互依赖。

这是我在不知道 classes 实际做什么的情况下所能得到的最详细信息。

面向对象编程的大部分复杂性决定了 classes 将如何依赖于其他 classes。或者,如果您正在处理其他人的代码,它会找出哪些 class 依赖于其他哪些 class。做对这一点是 IMO OOP 最重要的方面之一。

我认为当一个 class 依赖另一个对象时,将对象传递给其他对象的构造函数是正确的。这是一个很好的做法。下一步是弄清楚每个 class 中属于什么,这样它们就不需要循环依赖彼此。

首先 - 最好重新设计 类 以避免循环引用。请参阅 https://softwareengineering.stackexchange.com/questions/11856/whats-wrong-with-circular-references 进行讨论。

如果您必须有这样的引用(即构建具有 parent/child 关系的树),那么其中一个对象必须提供一种方法来延迟设置其中一个关系引用。

最直接 - 公开 属性 并在构造其他对象后设置它:

    wf = new WindowsForm(/*nothing*/);
    systemOutput = new SystemOutput(wf);
    system = new SystemCL(systemOutput, wf);
    wf.SetSystem(system); // method to make it less tempting to set later

还有多种方法可以使它更安全(工厂,添加时构造对象,..)甚至包括 immutable trees