Logo

dev-resources.site

for different kinds of informations.

Exploring Records in C#.

Published at
1/8/2025
Categories
csharp
net
microsoft
programming
Author
stevsharp
Categories
4 categories in total
csharp
open
net
open
microsoft
open
programming
open
Author
9 person written this
stevsharp
open
Exploring Records in C#.

Introduction

C# 9.0 introduced a powerful new feature: record. Designed to simplify immutable object creation, records prioritize data over identity, making them ideal for scenarios where value-based equality is essential. In this post, we'll dive into what records are, how to use them, their pros and cons, and practical use cases to help you decide when to use them in your projects.


What Are Records in C#?

A record is a special kind of class or struct designed to work seamlessly with immutable (read-only) data. Its most compelling feature is nondestructive mutation, allowing you to create modified copies of objects without altering the original. Beyond this, records excel in scenarios where you need types that simply hold or combine data.

In simple use cases, records eliminate boilerplate code while adhering to equality semantics ideal for immutable types. Whether you're working with data transfer objects (DTOs) or configuration models, records offer a clean and concise way to represent data.


Defining a Record

Defining a record is similar to defining a class or struct. Records can include fields, properties, methods, and more. They can implement interfaces and, in the case of class-based records, even inherit from other class-based records.


public record Person(string FirstName, string LastName);

This creates an immutable Person record with the following features:

  • Primary Constructor: Automatically initializes FirstName and LastName.
  • Value-Based Equality: Two Person records with the same values are considered equal.
  • Auto-Generated ToString(): Provides a human-readable string representation.

Features of Records

1. Immutability by Default

Records prioritize immutability, ensuring that data can't be modified after creation. With init accessors, you can initialize properties only during object creation:


public record Car
{
    public string Make { get; init; }
    public string Model { get; init; }
}

2. Value-Based Equality

Unlike classes that rely on reference-based equality, records compare property values:


var car1 = new Car { Make = "Tesla", Model = "Model S" };
var car2 = new Car { Make = "Tesla", Model = "Model S" };

Console.WriteLine(car1 == car2); // True

3. Nondestructive Mutation

With the with expression, you can create a modified copy of an existing record:


var car3 = car1 with { Model = "Model 3" };
Console.WriteLine(car3); // Car { Make = Tesla, Model = Model 3 }

4. Deconstruction

Records support deconstruction for easy extraction of properties:


var (make, model) = car1;
Console.WriteLine($"{make} {model}"); // Tesla Model S

5. Inheritance and Interfaces

Records can implement interfaces and inherit from other records:


public record Employee(string Name, int Id) : Person(Name);

When to Use Records

Use Cases:

  • Data Transfer Objects (DTOs): Simplify objects passed between layers.
  • Immutable Configuration: Store settings or configurations that shouldn't change.
  • Functional Programming: Handle immutable state and transformations effectively.
  • Representing Value-Based Data: E.g., geographic coordinates, complex numbers, etc.

Pros and Cons of Records

Pros

  • Simplified Syntax: Primary constructors reduce boilerplate code.
  • Immutability: Ensures consistent and predictable data handling.
  • Value-Based Equality: Automatically handles equality logic for properties.
  • Nondestructive Mutation: with expressions make updates cleaner and safer.
  • Readability: Auto-generated ToString() improves debugging and logging.

Cons

  • Limited to C# 9.0+: Requires .NET 5 or later, making it unavailable in older projects.
  • Learning Curve: Developers new to immutability might need time to adjust.
  • Performance Overhead: Extra work is required for equality checks in large objects.
  • Inheritance Limitations: Records only support inheritance within other records, not classes or structs.
  • Not Always Necessary: Overhead may not justify use in simple scenarios.

Comparison: Classes vs. Records vs. Structs

Feature Class Struct Record
Immutability Optional Optional Default
Equality Reference-Based Value-Based Value-Based
Inheritance Full Support None Limited to Records
Performance Reference Type (Heap) Value Type (Stack) Reference Type (Heap)
Syntax Verbose Concise Concise with Primary Constructor

Conclusion

Records introduce a new way to define types in C#, complementing the existing class and struct definitions. Here's how and when to use each:

  • Class Types: Use class definitions to create object-oriented hierarchies that focus on the responsibilities and behavior of objects. Classes emphasize reference-based equality and are ideal for encapsulating both state and behavior.
  • Struct Types: Use struct types for lightweight data structures that primarily store data and are small enough to be copied efficiently. Structs emphasize value-based equality and are best suited for scenarios where copying the entire object is inexpensive.
  • Record Types: Use record types when you want value-based equality and comparison, immutability, and the convenience of reference semantics. Records are perfect for scenarios where objects represent data and you don’t want to manually implement equality logic.
  • Record Struct Types: Use record struct types when you want the benefits of records—such as value-based equality and immutability—but for types that are small enough to copy efficiently. These are ideal for high-performance scenarios involving value semantics.



References

net Article's
30 articles in total
Favicon
Implementing JWT Authentication in .NET API
Favicon
ASP.NET MVC Suite Update: Aligning with .NET Changes
Favicon
Building a React CRUD App with a .NET API
Favicon
Exploring Records in C#.
Favicon
Stack vs Heap in C#: Key Differences and Usage
Favicon
DLL injection of managed code into native process
Favicon
Syncfusion Visual Studio Extensions Are Now Compatible With .NET 9.0
Favicon
Syncfusion Now Supports .NET 9!
Favicon
Open Source Tools for .NET MAUI
Favicon
Introducing Syncfusion’s First Set of Open-Source .NET MAUI Controls
Favicon
Bootcamp De Backend Com .NET Gratuito DIO + Randstad
Favicon
Building a Vue CRUD App with a .NET API
Favicon
Building an Angular CRUD App with a .NET API
Favicon
Bootcamp De Backend Com .NET Gratuito De DIO + Randstad
Favicon
Unlock Efficient Data Exchange: Import & Export Excel in ASP.NET Core
Favicon
How I Access the Dark Web Using This Search Engine 🔮
Favicon
Building a File Upload API in .NET
Favicon
EF Core 6 - This SqlTransaction has completed; it is no longer usable.
Favicon
Implement data validation in .NET
Favicon
Create a pagination API with .NET
Favicon
Create an API for DataTables with .NET
Favicon
Getting Started with .NET Aspire: Simplifying Cloud-Native Development
Favicon
Create a CRUD API with .NET
Favicon
Cultivating Trust and Innovation: Top 10 .NET Development Partners You Can Rely On
Favicon
Bootcamp De .NET Gratuito Com Oportunidade De Contratação
Favicon
Dapper mappings, which is best?
Favicon
Reading Request Headers Across Multiple .NET Core API Controllers
Favicon
Understanding DynamicData in .NET: Reactive Data Management Made Easy
Favicon
The Future of .NET Development: Skills and Expertise Needed in Tomorrow's Programmers
Favicon
🦙 Harnessing Local AI: Unleashing the Power of .NET Smart Components and Llama2

Featured ones: