$ dotnet run5 9 9heapN = 5Box1int a = 5;2int b = a;3b = 9;4var p = new Box { N = 5 };5var q = p;6q.N = 9;7Console.WriteLine($"{a} {b} {p.N}");8class Box { public int N; }stack frameintaintbBoxpBoxq59ref5 9 9
Violet card: the program; each step lights the line it runsSlots in the stack frame (type on top, value below); the Box object on the heapArrows: references · tokens: values and references being copiedIn front: the program Program.cs. On the right: the method's stack frame with four slots, a and b (int) and p and q (Box). Behind them: the heap. At the back: the terminal. Assigning an int copies the value, so changing b leaves a at 5. Assigning a Box copies only the reference (the arrow), so p and q share one object and the change made through q shows through p. The program prints 5 9 9. The C# language only promises the copy rules. Where data lives is the runtime's choice: here the four locals sit in the method's stack frame (or in CPU registers), and the Box lives on the managed heap. A value that is part of an object, like N, lives inside that object.

Two kinds of type

  1. Every C# type is either a value type or a reference type. A value-type variable holds the value itself. A reference-type variable holds a reference: an arrow to an object kept somewhere else, on the heap.

Value types: copy the value

Reference types: share the object

The result

What happens

// step 1/9 · two-kinds
value type       the variable holds the value          int, double, bool, char, struct
reference type   the variable holds a reference        class, string, arrays
                 (an arrow to an object on the heap)
the heap         memory for objects, run by .NET

The C# language only promises the copy rules. Where data lives is the runtime's choice: here the four locals sit in the method's stack frame (or in CPU registers), and the Box lives on the managed heap. A value that is part of an object, like N, lives inside that object. A reference-type variable can also hold null: no arrow at all. Using q.N when q is null throws a NullReferenceException.