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:

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:

Advantage: Ideal for lightweight data carriers.

Disadvantage: But normal struct lacks the immutability and equality benefits of record.

Records

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

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 the record struct perfect for lightweight models.

When to Use Record Struct

Use record struct when:

Stick to class when: