C# Record Types
Records are a type of reference or value type introduced in C# to simplify the creation of immutable objects.
They can be declared using record for reference types and record struct for value types.
Records automatically provide a suite of benefits that traditional classes do, but with less boilerplate code and more clarity.
public record Person(string FirstName, string LastName, int Age);
public record struct Point(double X, double Y, double Z);
Features of Record Types
Immutability by Default
Records in C# ensure that properties can only be set during object initialization using the init keyword. This design helps prevent bugs that occur due to unintended modifications, ensuring safer and more predictable code, particularly in multi-threaded environments.
public record Person(string FirstName, string LastName, int Age);
Person person = new("John", "Doe", 30);
// person.Age = 35; // This would result in a compile-time error
Value-based Equality
Unlike classes that use reference equality, records provide value equality out of the box. This means two record instances are considered equal if all their property values are the same.
var person1 = new Person("John", "Doe", 30);
var person2 = new Person("John", "Doe", 30);
Console.WriteLine(person1 == person2); // Outputs: True
Nondestructive Mutation
Records support modifications through with expressions, allowing the creation of new instances based on existing ones with altered property values without changing the original record.
Person updatedPerson = person with { Age = 35 };
Built-in Functionality
C# records come with automatically generated methods like ToString, GetHashCode, and Equals, and support deconstruction out of the box. This functionality reduces the need to manually override these methods, ensuring consistency and reducing potential errors.
Recommended by LinkedIn
Console.WriteLine(person.ToString()); // Outputs: Person { FirstName = John, LastName = Doe, Age = 30 }
Deconstructor in Records
When you define a record in C#, the compiler automatically generates a deconstructor method if the record is defined with positional parameters. This automatic deconstructor corresponds to the parameters defined in the primary constructor of the record.
Example of Automatic Deconstruction
Here’s a simple record with automatic deconstruction:
public record Person(string FirstName, string LastName, int Age);
You can then deconstruct this record like so:
var person = new Person("John", "Doe", 30);
var (firstName, lastName, age) = person; // Deconstruction
In this example, firstName, lastName, and age will be assigned the values from the respective properties of the person object.
Concise Syntax
One of the main attractions of records is their concise syntax. They can be defined in a single line, reducing clutter and making the code easier to read and maintain.
Practical Applications of Record Types
Record types are ideal for scenarios where data integrity and consistency are paramount.
They are particularly well-suited for use as
However, they are not suited for all scenarios, such as when mutable objects are required, like with certain ORM (Object-Relational Mapping) frameworks.
Reference: