DEV Community

Mariem Moalla
Mariem Moalla

Posted on

C# Performance Hack: Use record struct for Small, Immutable Models

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 }
Enter fullscreen mode Exit fullscreen mode

This makes record struct perfect for lightweight models.

When to Use Record Struct
Enter fullscreen mode Exit fullscreen mode

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)