- Published on
Everything You Need to Know About Records in C#
Overview
In C#, a record is a reference type that represents an immutable set of data, similar to a struct. Unlike a struct, a record has several built-in features that make it easier to use, such as value-based equality, deconstruction, and support for positional and named arguments.
In this article, we will discuss everything you need to know about records in C#, including their syntax, features, and use cases.
Syntax:
A record is defined using the record
keyword, followed by the name of the record and its members. For example:
public record Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
public int Age { get; init; }
}
This defines a record called Person
with three properties: FirstName
, LastName
, and Age
. The init
keyword specifies that the properties can only be set during object initialization, and not after.
Features:
Records in C# have several built-in features that make them easier to use and work with. Some of these features include:
1. Value-based equality:
Records have built-in support for value-based equality, which means that two record instances are considered equal if all their properties have the same values. For example:
var person1 = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
var person2 = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
Console.WriteLine(person1 == person2); // Output: True
2. Deconstruction:
Records can be deconstructed into their individual properties using the Deconstruct
method. For example:
var person = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
var (firstName, lastName, age) = person;
Console.WriteLine($"{firstName} {lastName}, {age}"); // Output: John Doe, 30
3. Positional and named arguments:
Records can be initialized using either positional or named arguments. For example:
var person = new Person("John", "Doe", 30);
var person = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
var person = new Person(FirstName: "John", LastName: "Doe", Age: 30);
4. Inheritance:
Records can inherit from other records or classes, just like classes. For example:
public record Employee : Person
{
public string EmployeeId { get; init; }
}
5. Immutability:
Records are immutable by default, which means that their properties cannot be changed after they are initialized. This helps ensure that records are always in a valid state and can be safely passed between threads.
6. With-expressions:
Records have built-in support for with-expressions, which allow you to create a new record instance with one or more properties changed. For example:
var person1 = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
var person2 = person1 with { FirstName = "Jane" };
Console.WriteLine(person1.FirstName); // Output: John
Console.WriteLine(person2.FirstName); // Output: Jane
Use cases:
Records are useful in many situations where you need to represent a set of data that is immutable and can be compared for equality. Some common use cases include:
1. Data transfer objects:
Records are often used as data transfer objects (DTOs) in applications that communicate with external services or APIs. DTOs typically represent a set of data that needs to be sent or received, and records provide a convenient and efficient way to define them.
2. Domain models:
Records are also useful for representing domain models in object-oriented applications. Domain models are typically representations of business entities or concepts, and records provide a lightweight and efficient way to define them.
3. Immutable collections:
Records are also useful for creating immutable collections of data. For example, you could define a record called PersonList
that contains a list of Person
records, and ensure that the list cannot be modified once it is initialized.
4. API responses:
Records are also useful for representing API responses in web applications. API responses typically consist of a set of data that is returned to the client, and records provide a clean and efficient way to define them.
Conclusion:
In conclusion, records are a powerful and efficient feature in C# that provide a convenient way to represent immutable sets of data. With built-in support for value-based equality, deconstruction, positional and named arguments, inheritance, immutability, and with-expressions, records are well-suited for a wide range of use cases, including data transfer objects, domain models, immutable collections, and API responses.