Please take a look at the code below:
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;
}
}
What I am trying to achieve here is to store several objects of MyClass type that hold references to the other members of the same type. When I initialize the otherObjectsOfSameClass list of each object in the MainClass constructor, I add the other object to that list. When I initialize the myObject1, the myObject2 is still null - that is expected. The list should hold a reference to myObject2, even if it's null.
However, even after I initialize myObject2, it is still null in the otherObjectsOfSameClass list of the myObject1. For some reason, the object reference in that list doesn't update. Can someone please explain this behavior? Am I misunderstanding something fundamental here?
EDIT: I realized this can be reproduced with an even simpler test code:
List<MyClass> myList = new List<MyClass> { myObject1, myObject2 };
myObject1 = new MyClass();
myObject1.TestMethod(); // works fine
myList[0].TestMethod(); // throws null reference exception
It seems that adding an uninitialized object to a list and initializing it afterwards doesn't change it in the list - even though it should be added by reference, not by value...
Variables and elements of lists store values. For a reference type like MyClass
, That value is either a reference to an object, or the value null
- nothing.
In the working case,
myObject2.otherObjectsOfSameClass = new List<MyClass> { myObject1 };
The list contains the reference that the variable myObject1
stores. myObject1
stores a reference to a MyClass
object, not null, so the list also stores a reference to that same object, so when you access the list, no exceptions. Note that the values of myObject1
and myObject2.otherObjectsOfSameClass[0]
are unrelated. It just so happens that their values are references to the same object, but otherwise changing the value of one of them would not affect the other. For example, doing:
myObject1 = null;
would not make myObject2.otherObjectsOfSameClass[0]
null as well.
OTOH, when this is run:
myObject1.otherObjectsOfSameClass = new List<MyClass> { myObject2 };
myObject2
stores null
, so the list stores null. Again, the values of myObject2
and myObject1.otherObjectsOfSameClass[0]
are unrelated. It just so happens that they are both null. Then you say:
myObject2 = new MyClass();
which changes the value of myObject2
to a reference to an object. This has no effect on the value of myObject1.otherObjectsOfSameClass[0]
. After all, they are two different variables.