C#  

Record, Record Struct, and Structural Equality in C#

Modern C# provides powerful tools for modeling data more precisely; among the most impactful are records, record structs, and structural equality.

This becomes especially important when applying best practices or working with Domain Driven Design (DDD).

What Is Structural Equality?

Structural equality means that two objects are considered equal if their values are equal, not if they reference the exact memory location.

In other words, equality is determined by comparing the data inside the object rather than its identity.

In traditional classes, equality is reference-based by default.

Two instances with the same values are still considered different unless you override Equals and GetHashCode. Records change this behavior.

var a = new Person("Alice", 30);
var b = new Person("Alice", 30);

Console.WriteLine(a == b); // true with records

With records, this works out of the box because equality is value-based.

Records: Reference Types with Structural Equality

A record is a reference type that behaves like a value. It is immutable by default and supports structural equality.

public record Person(string Name, int Age);

var original = new Person("Alice", 30);
var updated = original with { Age = 31 };

This makes records ideal for domain models that represent concepts rather than identities, such as configurations, requests, responses, or domain value objects.

Record Structs: Value Types with Structural Equality

A record struct combines the benefits of value types with record semantics. It lives on the stack when possible, avoids heap allocations, and still provides structural equality.

public record struct Money(decimal Amount, string Currency);

Record structs are especially useful for small, immutable value objects that are frequently created and passed around, such as money, coordinates, or measurements.

Why Structural Equality Matters in DDD

Domain-Driven Design makes a clear distinction between Entities and Value Objects. Entities have identity and change over time. Value objects do not have identity, they are defined entirely by their values.

Structural equality is what allows value objects to behave correctly.

public record Address(string Street, string City, string ZipCode);

Two addresses with the same values should be considered equal. Records make this the default behavior, aligning perfectly with DDD principles and eliminating subtle bugs caused by reference comparison.

When to Use What

Use records when modeling immutable data. Use record structs when the object is small, immutable, frequently instantiated, and performance-sensitive. Use classes when identity, inheritance, or controlled mutability is required.