List 中的 NULL 对象即使在初始化后仍保持 NULL

A NULL object in a List stays NULL even after initialization

请看下面的代码:

public class MainClass
{
    MyClass myObject1, myObject2;

    public MainClass()
    {
        myObject1 = new MyClass();
        myObject1.otherObjectsOfSameClass = new List<MyClass> { myObject2 };

        myObject2 = new MyClass();
        myObject2.otherObjectsOfSameClass = new List<MyClass> { myObject1 };
        
        myObject2.otherObjectsOfSameClass[0].TestMethod(); // works fine
        myObject1.otherObjectsOfSameClass[0].TestMethod(); // throws null reference exception
    }
}

class MyClass
{
    public List<MyClass> otherObjectsOfSameClass;

    public bool TestMethod()
    {
        return true;
    }
}

我在这里试图实现的是存储多个 MyClass 类型的对象,这些对象保存对同一类型的其他成员的引用。当我在 MainClass 构造函数中初始化每个对象的 otherObjectsOfSameClass 列表时,我将另一个对象添加到该列表中。当我初始化 myObject1 时,myObject2 仍然为空 - 这是预期的。该列表应包含对 myObject2 的引用,即使它为 null。

然而,即使在我初始化 myObject2 之后,它在 myObject1 的 otherObjectsOfSameClass 列表中仍然为空。由于某种原因,该列表中的对象引用不会更新。有人可以解释这种行为吗?我是不是误解了一些基本的东西?

编辑:我意识到这可以用更简单的测试代码重现:

        List<MyClass> myList = new List<MyClass> { myObject1, myObject2 };

        myObject1 = new MyClass();

        myObject1.TestMethod(); // works fine
        myList[0].TestMethod(); // throws null reference exception

似乎将未初始化的对象添加到列表并在之后对其进行初始化并不会在列表中更改它 - 即使它应该通过引用而不是值添加...

这是有道理的 - 当您此时初始化 myList = new List<MyClass> { myObject1, myObject2 }; 时,您正在创建一个新列表,并且该列表中的值将评估为 null。稍后初始化 myObject1 或 myObject2 的事实不会改变 myList 中存储了空值的事实。

这是因为 myObject1 在实例化时为 null - 没有它指向的内存地址,也没有它所引用的对象。另一方面,如果您要初始化 myObject1 = new someObject(),然后初始化 myList,它不会是未定义的,并且会有对 myObject1 的引用,这样如果您更新 myObject1,更新也会反映出来在 myList

列表的变量和元素存储值。对于像 MyClass 这样的引用类型,该值要么是对 对象 的引用,要么是值 null - 什么都没有。

在工作情况下,

myObject2.otherObjectsOfSameClass = new List<MyClass> { myObject1 };

该列表包含变量 myObject1 存储的引用。 myObject1 存储对 MyClass 对象的引用,而不是 null,因此列表也存储对同一对象的引用,因此当您访问列表时,没有例外。请注意,myObject1myObject2.otherObjectsOfSameClass[0] 的值是不相关的。 恰好它们的值是对同一个对象的引用,但是改变其中一个的值不会影响另一个。例如,做:

myObject1 = null;

也不会使 myObject2.otherObjectsOfSameClass[0] 为空。

OTOH,当这是 运行:

myObject1.otherObjectsOfSameClass = new List<MyClass> { myObject2 };

myObject2 存储 null,因此列表存储 null。同样,myObject2myObject1.otherObjectsOfSameClass[0] 的值是不相关的。碰巧它们都是空的。然后你说:

myObject2 = new MyClass();

myObject2 的值更改为对对象的引用。这对 myObject1.otherObjectsOfSameClass[0] 的值没有影响。毕竟是两个不同的变量