*
Previous Memory Management in C# Pattern Matching in C# Next

Records in C#

Records in C# are special reference types introduced in C# 9.0 designed to make working with immutable data objects easier. They are ideal for data-centric models (like DTOs) where you primarily care about the data the object holds, not its identity.

Unlike regular classes, records automatically provide value-based equality (two record instances are equal if all their properties are equal), built-in immutability, and concise syntax for creating and cloning objects.

Syntax Example

Basic Record

public record Person(string Name, int Age);

This defines a record with two properties: Name and Age. You can instantiate it like this:

var p1 = new Person("Alice", 25);
var p2 = new Person("Alice", 25);

Console.WriteLine(p1 == p2); // True - value equality

Here, == compares property values, not object references (unlike classes).

With Expression (Cloning)

var p3 = p1 with { Age = 30 };
Console.WriteLine(p3); // Output: Person { Name = Alice, Age = 30 }

The with expression creates a copy of the record with modified properties while keeping the original immutable.

Record with Body

public record Employee
{
    public string Name { get; init; }
    public string Department { get; init; }
    public int Salary { get; init; }

```
public void DisplayInfo() => 
    Console.WriteLine($"{Name} works in {Department} earning {Salary}");
```

} 

Best Practices for Using Records

  • Use records for data-centric, immutable models (e.g., DTOs, API responses, configuration data).
  • Prefer positional records for simple immutable data structures.
  • Use init accessors to maintain immutability while allowing initialization.
  • Use with expressions instead of modifying existing record instances.
  • Combine records with pattern matching for concise and readable logic.

When to Use Records

  • When you need value-based equality (objects are equal if their data matches).
  • For immutable data transfer objects (e.g., requests/responses in APIs).
  • For representing domain entities that don’t require identity (e.g., settings, coordinates, etc.).
  • In functional programming patterns where immutability is preferred.

When Not to Use Records

  • When your type requires mutable state (e.g., entities in ORMs like EF Core that change over time).
  • When reference equality is important (e.g., caching, singleton patterns).
  • When performance overhead from copying objects is a concern.
  • When you need full control over equality semantics (use classes instead).

Precautions When Using Records

  • Records are reference types, but equality is value-based—be careful if you rely on identity.
  • Cloning with with expressions creates new instances — may increase memory usage for large data.
  • init-only properties mean you can’t modify data after creation — design accordingly.
  • Records are not ideal for large mutable collections — use structs or regular classes instead.
  • Be cautious with inheritance: record inheritance behaves differently (it uses compiler-generated Deconstruct and equality methods).

Advantages Over Normal Classes or Collections

  • Value equality: Automatically compares data rather than references.
  • Concise syntax: Less boilerplate (no need to override Equals, GetHashCode, or ToString).
  • Immutability: Encourages safer, side-effect-free code.
  • Pattern matching support: Seamless integration with switch expressions.
  • Easy cloning: Modify copies efficiently using the with expression.

Example Comparison — Class vs Record

Using a Class

class PersonClass
{
    public string Name { get; set; }
    public int Age { get; set; }
}

var c1 = new PersonClass { Name = "Alice", Age = 25 };
var c2 = new PersonClass { Name = "Alice", Age = 25 };
Console.WriteLine(c1 == c2); // False (reference comparison) 

Using a Record

record PersonRecord(string Name, int Age);

var r1 = new PersonRecord("Alice", 25);
var r2 = new PersonRecord("Alice", 25);
Console.WriteLine(r1 == r2); // True (value comparison) 

Summary

  • Use Records for immutable, data-centric types where value equality and conciseness matter.
  • Use Classes when you need mutable objects or rely on reference identity.
  • Records promote cleaner, safer, and more expressive code — especially useful in modern C# architectures (like APIs and microservices).
Back to Index
Previous Memory Management in C# Pattern Matching in C# Next
*
*