Lesson 15 of 40
Core C#
Intermediate
โฑ 30 min
Structs, Records & Value Types
Choose the right type for the job โ structs for stack-allocated value semantics, records for immutable data, and understand boxing/unboxing.
Part 1: struct vs class
| Feature | struct | class |
|---|---|---|
| Allocation | Stack (usually) | Heap |
| Equality | Value equality | Reference equality (by default) |
| Default | All fields = default | null |
| Inheritance | No class inheritance | Yes |
| Use when | Small, short-lived data | Complex objects with behavior |
Part 2: readonly struct
public readonly struct Money
{
public decimal Amount { get; }
public string Currency { get; }
public Money(decimal amount, string currency)
=> (Amount,Currency) = (amount,currency);
public Money Add(Money other) => new(Amount + other.Amount, Currency);
}
{
public decimal Amount { get; }
public string Currency { get; }
public Money(decimal amount, string currency)
=> (Amount,Currency) = (amount,currency);
public Money Add(Money other) => new(Amount + other.Amount, Currency);
}
Part 3: record and record struct
// Positional record โ auto property, equality, ToString
public record Person(string Name, int Age);
// Non-destructive mutation (with expression)
var alice = new Person("Alice", 30);
var olderAlice = alice with { Age = 31 };
// record struct โ stack allocated, value equality
public record struct Point(double X, double Y);
public record Person(string Name, int Age);
// Non-destructive mutation (with expression)
var alice = new Person("Alice", 30);
var olderAlice = alice with { Age = 31 };
// record struct โ stack allocated, value equality
public record struct Point(double X, double Y);
Part 4: Boxing & Unboxing
// Boxing โ value type โ object (heap allocation!)
int x = 42;
object boxed = x; // boxed
// Unboxing โ cast back
int unboxed = (int)boxed;
// Avoid boxing in hot paths!
// Use List<int> not ArrayList for int storage
// Use generic constraints instead of object params
int x = 42;
object boxed = x; // boxed
// Unboxing โ cast back
int unboxed = (int)boxed;
// Avoid boxing in hot paths!
// Use List<int> not ArrayList for int storage
// Use generic constraints instead of object params
C# in Visual Studio 2026
๐ This lesson is part of the book C# in Visual Studio 2026 by Dr. Liew Voon Kiong.
View on Amazon Kindle Edition