Isaac.

C# Records

Learn how to use C# records for immutable data types with less boilerplate.

By EMEPublished: February 20, 2025
csharprecordsimmutabilitydata classesdotnet

A Simple Analogy

Imagine a student ID card. Once created, it never changes—no updates to the information. Records in C# are like that: immutable, value-based objects designed for data that doesn't change.


What Are C# Records?

Records (introduced in C# 9) are reference types designed for immutable data. They provide automatic equality comparison, deconstruction, and are perfect for data transfer objects, value objects, and configuration.


Why Use Records?

  • Less boilerplate: No need for equals/getHashCode
  • Immutable by default: Encourages functional programming
  • Value-based comparison: Compares content, not identity
  • Readable: Intent is clear: this is immutable data

Record Syntax

Basic Declaration

public record Person(string Name, int Age);

var person = new Person("Alice", 30);

With Methods

public record Product(string Id, string Name, decimal Price)
{
    public bool IsExpensive => Price > 100;
}

Positional and Named Properties

var p = new Person("Bob", 25);
var (name, age) = p;  // Deconstruction

var p2 = p with { Age = 26 };  // Create modified copy

Records vs. Classes

| Feature | Record | Class | |---------|--------|-------| | Immutability | By default | Must enforce manually | | Equality | By value | By reference | | Boilerplate | Minimal | More code | | Use case | Data DTOs | Complex logic |


Practical Example

// E-commerce order
public record Order(
    string Id,
    DateTime CreatedAt,
    List<OrderItem> Items,
    decimal Total)
{
    public bool IsComplete => Items.Any() && Total > 0;
}

// Usage
var order = new Order("ORD-123", DateTime.Now, items, 199.99);
var updated = order with { Total = 189.99 };  // Immutable copy

Related Concepts to Explore

  • Value objects in domain-driven design
  • Immutability patterns
  • Record inheritance
  • Init-only properties

Summary

C# records simplify creating immutable data types. Use them for DTOs, value objects, and configuration to write cleaner, safer code with less boilerplate.