When you learn about an object-oriented language like Java or C#, you come across the concept of reference semantics, and to many, it’s pretty confusing at first.
This article is meant to shed some light on the matter, explaining why
a = b;
can mean different things under different circumstances.
A short notice: Despite most of this article not being directly related to Unity, I’m still using Unity-style variable names, which divert from C# standard.
Variables and assignments
To start with a quick refresher on some basics…
A variable, as is something everyone learns at the start of their programming career, is a space in the computer’s memory that contains data, like a number.
int number = 5;
This line orders the computer to reserve some space (enough to fit an int
value in it, which is 32 bit) in an appropriate place in the memory, and write the number 5
in it.
Using the =
operator means that the statement is an “assignment”, which means a value is written to a variable. An assignment always has to have a variable on the left side (let’s ignore properties for now…), and on the right side, anything that eventually evaluates to a value that matches the variable type – this includes another variable of the same type:
int anotherNumber = number;
Here, we make another int
variable and copy over the value of the number
variable. In the end, we have two variables in our memory that each contain the number 5
.
Objects and references
An “object”, in the context of an object-oriented language, is some amount of data that’s structured in a specific way. For example, you could define a class like this:
public class Person { public string name; public int age; public Person(string name. int age) { this.name = name; this.age = age; } }
…and then create an instance of that class, which would be an object:
Person mum = new Person("Emily", 40);
Now, when you use the assignment operator =
again…
Person mathTeacher = mum;
…one could expect that we end up with two Person
objects, but that is not the case. To allow us to represent things like “my mum is also my math teacher”, instances of classes have reference semantics.
When we create an int
variable, the program makes space to write a number in it, because int
is one of the “primitive types“. However, with class instance objects, the space where the Person
object with its name
string is stored in memory is a different one, called the “heap“. Imagine this reserved space as a big pile where all the objects you make are thrown onto. And the variable you make will contain an “address” that allows the program to precisely find the object on that pile.
So, when you write…
Person mathTeacher = mum;
…the same thing as with an int
variable happens. The value of the variable on the right is copied over to the variable on the left. That value, however, is not the Person
object, but the address that points to where that object is stored. So we end up with two variables referencing the same object. This means that, when we do this…
mathTeacher.name = "Vivian";
…and afterwards ask the program about…
mum.name
…we will get "Vivian"
as the answer, since we changed the name of the only Person
object we currently have.
About C# structs
Structs in C# are similar to classes in that we can define a thing that has a specific set of properties. The main difference between classes and structs is that structs don’t have reference semantics, which means that, for example, a Unity Vector3
will not get its own place in the heap, but will be stored directly in the variable it’s assigned to.
Vector3 boxPosition = new Vector3(10, 0, 0);
This means that, if we assign the value of a variable to another variable…
Vector3 spherePosition = boxPosition;
…the entire Vector3
value is copied over. And as a result, in this example, we can move the box around without affecting the position of the sphere.
Conclusion
Despite reference semantics not being an advanced topic, it can be quite the speed bump for newcomers to object-oriented programming. I hope that this article helps understanding unexpected behavior in assignment statements.