Skip to content
Theory · Classes and objects · lesson 10 of 11

Objects and references

In the theme on arrays, the assignment int[] b = a; did not create a second array but gave the first one another name. Objects of classes behave the same way:

C#
var a = new House("red");
House b = a;
b.Color = "blue";
Console.WriteLine(a.Color); // blue

class House
{
    public string Color { get; set; }

    public House(string color) => Color = color;
}

Let's go through it line by line:

  1. var a = new House("red"); builds a red house and gives it the name a.
  2. House b = a; does not build a second house. Now the same house has two names: a and b.
  3. b.Color = "blue"; repaints this one house.
  4. That is why Console.WriteLine(a.Color) prints blue: a and b show the same house.

Picture a house standing on a street, and in your pocket a slip of paper with its address. The variable House a is the slip, not the house. The line House b = a; copies the address onto a second slip: there are now two slips, but still one house. Whoever comes to that address to paint it, the very same house gets painted.

The variable holds a reference

A class is a reference type, like an array. The object sits in memory on its own, and the variable holds a reference to it: that address on the slip. Assignment copies what the variable holds, so b = a copies the address, not the house.

In the widget, an object variable shows an arrow and a short form of the object instead of a value. → House { Color = "red" } reads like this: the variable leads to a house whose Color is "red". Press "Next step" and read the caption: it says whether the names share one house.

LiveTwo names, one housestep 1 of 10 · frames: 1

A house is built, and the variable a gets a reference to it.

The step caption says whether the names share one house

As long as two variables hold one reference, a change through either name is visible through the other. A method that is passed an object gets one more copy of the reference and changes the same house. Interviewers often ask what happens after b = a if the type of a is a class. The answer: both variables lead to one object, and changes through one are visible through the other.

The slip can be rewritten

The address on a slip can be erased and a new one written. After b = new House("red"), the variable b leads to a new house and a to the old one. The old house does not change: assigning to a variable does not touch the object.

The same goes for a method parameter. If you write h = new House("pink"); inside Repaint, only the copy of the reference in h changes. The variable a in the calling code still leads to the old house.

A reference to nowhere: null

Here the slip and the reference differ. On a slip you can get the address wrong and end up at another house. A reference in C# cannot be spoiled like that: it either leads to a real object or is empty.

An empty reference leads to no object and is written as the word null. It is a slip with no address written on it. Such a reference can sit in a variable or in an element of an array whose elements are of a reference type, such as House:

C#
House[] street = new House[3];
Console.WriteLine(street[0] == null); // True
street[0] = new House("red");
Console.WriteLine(street[0].Color);   // red
Console.WriteLine(street[1] == null); // True

class House
{
    public string Color { get; set; }

    public House(string color) => Color = color;
}

An array of numbers new int[3] is filled with zeros, and an array of houses new House[3] with empty references. These are three slips without addresses: not a single house has been built yet. A house appears only when the result of new is put into an element.

Comparing with ==

For objects of the classes you write yourself, == compares references, as it does for arrays: it checks whether it is one house, not whether the houses are alike.

C#
var a = new House("red");
var b = new House("red");
House c = a;
Console.WriteLine(a == b); // False
Console.WriteLine(a == c); // True

class House
{
    public string Color { get; set; }

    public House(string color) => Color = color;
}

a and b have the same color, but they are two different houses at two addresses, so a == b gives false. And c is a second slip with the address of house a, so a == c gives true.

Common mistake

An array of objects was created, but the objects themselves were not:

C#
House[] street = new House[3];
street[0].Color = "red"; // ✗
Console.WriteLine(street[0].Color);

class House
{
    public string Color { get; set; }

    public House(string color) => Color = color;
}
TEXT
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.

The program compiles, but when it runs it stops at the second line with a NullReferenceException. street[0] holds null: there is no address, so there is nowhere to go to paint. The compiler gives no warning here: it does not track which elements of an array have already got objects. Build the house first: street[0] = new House("red");.

Key points

  • A variable whose type is a class holds a reference to an object: House b = a; copies the reference and gives the same object a second name.
  • A change to an object through one name is visible through all the others; a method that gets an object changes that same object.
  • Assigning a new reference to a variable, b = new House("red"), changes only that variable, not the object.
  • null is a reference that leads nowhere: using a field or a property through it stops the program with a NullReferenceException.