1

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...

3
  • 2
    myObject2 is not initialized, so you have myObject1.otherObjectsOfSameClass = new List<MyClass> { null };so the exception... even if you create one that you assign to myObject2 after, you have null in the list. Commented Dec 15, 2020 at 1:03
  • 1
    The list item and the variable no longer referred to the same object the moment you reassigned the variable. Variables and lists hold values, and sometimes those values are references. Sometimes two variables, two list items, or a mix, hold the same value, which can be a reference to the same object. But reassigning one does not impact the other. Commented Dec 15, 2020 at 1:06
  • Got it. So I just have initialize these objects before adding them to lists, an easy fix. Thank you very much, guys. Commented Dec 15, 2020 at 1:17

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you very much for such an elaborate explanation. I get it now. I just thought that even an uninitiated but declared object already has a pointer which should be passed to that list. All is clear now. Thanks again!
@Sweeper when you say "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;" In this example, you are removing the reference, not updating the object. Try actually setting some property on myObject1 and it will update myObject2.otherObjectsOfSameClass[0] as well
@cloudComputer107 If you are setting some property of myObject1, you are not "changing the value stored in myObject1". To change the value of a variable, you should use = on that variable, i.e. myObject1 = .... myObject1.SomeProperty = ... is changing the value of SomeProperty. It has nothing to do with the value of myObject1. You are mutating the object referenced by the reference stored in myObject1, though.
Yes you are mutating it, which is why I think it is confusing to say that the values are unrelated
2

It makes sense - when you initialize myList = new List<MyClass> { myObject1, myObject2 }; at this time you are creating a new list, and the value in that list will evaluate to null. The fact that you initialize myObject1 or myObject2 later on will not change the fact that you have nulls stored in myList.

This is because myObject1 is null at the time of instantiation - there is no memory address that it is pointing to, no object that it is referring to. If, on the other hand, you were to initialize myObject1 = new someObject() and then initialize myList, it will not be undefined and there will be a reference to myObject1 such that if you update myObject1 the update will also be reflected in myList

1 Comment

Okay, I think I got it. I thought that even a null object still has a memory address, but that memory is just not used yet. So, considering my example, I guess I should first initialize both myObject1 and myObject2, and only then add them to each other's lists?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.