Types · value vs reference
struct vs class in C#
The declaration keyword matters less than the assignment semantics: a class variable holds a reference to one shared object; a struct variable holds its own copy. Everything else follows from that.
class: two names, one object
Assigning a class variable copies the reference, not the object. Both names point at the same box:
class Dog
{
public string Name;
public Dog(string name) { Name = name; }
}
Dog a = new Dog("Rex");
Dog b = a; // b is a SECOND NAME for the same object
b.Name = "Max"; // renaming through b…
Console.WriteLine(a.Name); // …renamed it for a too
class Dog
{
public string Name;
public Dog(string name) { Name = name; }
}
Dog a = new Dog("Rex");
Dog b = new Dog("Rex"); // a genuinely new, separate object
b.Name = "Max";
Console.WriteLine(a.Name); // untouched
Console.WriteLine(a == b); // == compares REFERENCES: different objects → False
// (same content, different identity)
struct: assignment makes a copy
Structs flip the semantics. Assigning a struct copies the whole value — the two variables are independent from that moment:
struct Point
{
public int X;
public Point(int x) { X = x; }
}
Point a = new Point(1);
Point b = a; // FULL COPY — b has its own storage
b.X = 99;
Console.WriteLine(a.X); // 1 — a was never touched
Console.WriteLine(b.X); // 99
Honesty note: the browser engine currently treats structs like classes (reference semantics) — that exact program in Visual Studio prints 1 and 99 as shown. The concept stands; verify copy behavior in a real compiler until the engine grows value semantics.
The gotcha this explains
Ever changed a field through one variable and been surprised another variable "saw" the change? That was reference aliasing. And its mirror: changed a struct field inside a method, and the caller's copy didn't update? Value copying. Both are the correct behavior for their kind — the bug is expecting the other kind:
| Scenario | class | struct |
|---|---|---|
b = a; copies… | the reference | the whole value |
Mutating through b affects a? | Yes — same object | No — separate copy |
a == b means… | same identity | same field values (if == is defined) |
| Lives… | on the heap, garbage-collected | inline (stack or inside its owner) |
Which one to pick?
The practical rule most codebases follow:
- Default to
class. Entities with identity (a User, an Order, a Dog) — identity is exactly what reference semantics model. - Reach for
structfor small (< ~16–24 bytes), immutable value-like data where copying is cheap and natural: coordinates, money amounts, dates, colors. The .NET library's ownint,double,bool,DateTime,Guidare all structs. - Mutable structs are a trap. A copy mutating itself silently is almost never what you meant — if the struct needs to change, it usually wants to be a class.
One-minute self-test
Run this in the playground and predict the output before pressing Run — it's the aliasing demo from above with the names swapped:
Dog x = new Dog("One");
Dog y = x;
y = new Dog("Two");
Console.WriteLine(x.Name); // predict: One or Two? (reference vs object)
If you said "One" — assigning new Dog("Two") to y re-points y's reference; it never touches the object x names. Related reading: var vs explicit types.