When designing data models in C#, the choice between class, struct, and record, can significantly impact performance, and memory usage.
But what makes record struct such a good fit for lightweight models compared to classes?
Classes: The Default Choice
By default, most developers reach for class. Classes are reference types:
- They live on the heap.
- Variables hold references (pointers) to objects.
- Garbage Collection (GC) must clean them up when no longer used.
Advantage: Good for large, complex objects that are shared or mutated.
Disadvantage: Overkill for small, short-lived, immutable data models.
Structs
A struct is a value type:
- Allocated on the stack.
- Copied by value, not reference.
- Faster for small, short-lived objects.
- No GC overhead for stack allocations.
Advantage: Ideal for lightweight data carriers.
Disadvantage: But normal struct lacks the immutability and equality benefits of record.
Records
- A reference type.
- Record classes behave similarly to regular classes in terms of memory allocation (on the heap) and assignment (reference copying).
- Value-based equality (== compares properties, not references).
public record Point(int X, int Y); var p1 = new Point(5, 10); var p2 = new Point(5, 10); var p3 = new Point(10, 20); Console.WriteLine(p1 == p2); // True (same values) Console.WriteLine(p1 == p3); // False (different values) // For classes: public class PointClass { public int X { get; init; } public int Y { get; init; } } var c1 = new PointClass { X = 5, Y = 10 }; var c2 = new PointClass { X = 5, Y = 10 }; Console.WriteLine(c1 == c2); // False (different references) Record Struct : The Best of Both Worlds Combines the performance of a struct (stack-allocated, lightweight). With the features of a record (immutability, value equality, with expressions). public readonly record struct Point(int X, int Y); var p1 = new Point(10, 20); var p2 = new Point(10, 20); // Value equality Console.WriteLine(p1 == p2); // True // With-expression works var p3 = p1 with { X = 30 }; Console.WriteLine(p3); // Point { X = 30, Y = 20 }
This makes record struct perfect for lightweight models.
When to Use Record Struct
Use record struct when:
- You need small, immutable, value-like models.
- You care about low memory and avoiding heap/GC overhead.
Stick to class when:
- Objects are large, complex, or mutable.
- You need shared instances.
Top comments (0)