The best way to understand this is to fully understand what variables are; variables are, simply put, placeholders that hold values.
So what exactly is this value? In a reference type, the value stored in the variable is the reference (the address so to speak) to a given object. In a value type, the value is the object itself.
When you do AnyType y = x;
what really happens is that a copy of the value stored in x
is made and is then stored in y
.
So if x
is a reference type, both x
and y
will point to the same object because they will both hold identical copies of the same reference. If x
is a value type then both x
and y
will hold two identical but distinct objects.
Once you understand this, it should start to make sense why your code behaves the way it does. Lets study it step by step:
Person person_1 = new Person();
Ok we are creating a new instance of a value type. According to what I explained previously, the value stores in person_1
is the newly created object itself. Where this value is stored (heap or stack) is an implementation detail, its not relevant at all to how your code behaves.
person_1.name = "Person 1";
Now we are setting the variable name
which happens to be a field of person_1
. Again according to previous explanations, the value of name
is a reference pointing to somewhere in memory where the string "Person 1"
is stored. Again, where the value or the string are stored is irrelevant.
Person person_2 = person_1;
Ok, this is the interesting part. What happens here? Well, a copy of the value stored in person_1
is made and stored in person_2
. Because the value happens to be an instance of a value type, a new copy of said instance is created and stored in person_2
. This new copy has its own field name
and the value stored in this variable is, again, a copy of the value stored in person_1.name
(a reference to "Person 1"
).
person_2.name = "Person 2";
Now we are simply reassigning the variable person_2.name
. This means we are storing a new reference that points to a new string
somewhere in memory. Do note, that person_2.name
originally held a copy of the value stored in person_1.name
so whatever you do to person_2.name
has no effect on whatever value is stored in person_1.name
because you are simply changing... yeah exactly, a copy. And thats why your code behaves the way it does.
As an exercise, try to reason out in a similar way how your code would behave if Person
were a reference type.