The record
type is a feature introduced in C# 9.0 that allows you to define a reference type that focuses on immutability and structural equality.
Unlike traditional classes, record
types are designed to represent data rather than behaviors. This makes them suitable for modeling data, for example.
Key Features of Record Types
Immutability by Default: record
types are immutable by default, meaning their properties are set once at the time of creation and cannot be modified afterward.
Structural Equality: record
types implement structural equality, which means that two instances of a record
are considered equal if their properties have the same values, unlike reference equality that applies to classes.
Destructuring: record
types support destructuring, which allows you to easily extract values from a record
into individual variables.
Pattern Matching: record
types allow pattern matching, which facilitates value comparison and data extraction in pattern matching operations.
How to Use record
Defining a Record
To define a record
type, use the record
keyword followed by the type name and the property list. Here is a basic example:
public record Person(string Name, int Age);
In this example,
Person
is arecord
with two properties:Name
andAge
.- The constructor, properties, and equality methods are automatically generated by the compiler.
Accessing Properties
Accessing properties of a record
is done directly, just like in classes:
Console.WriteLine(person.Name); // Output: Ana
Console.WriteLine(person.Age); // Output: 30
Structural Equality
Two instances of a record
are equal if their properties have the same values:
var person1 = new Person("Ana", 30);
var person2 = new Person("Ana", 30);
var person3 = new Person("Juan", 25);
Console.WriteLine(person1 == person2); // Output: True
Console.WriteLine(person1 == person3); // Output: False
record
types automatically override the Equals
and GetHashCode
methods to provide structural equality.
Immutability
By default, the properties of a record
are immutable. This means they cannot be modified once the instance has been created.
var product = new Product("Tablet", 300.00m);
// product.Price = 250.00m; // Compilation error: cannot modify a readonly property
Destructuring
You can destructure a record
into its individual components using destructuring syntax:
var (name, age) = person;
Console.WriteLine($"Name: {name}, Age: {age}"); // Output: Name: Ana, Age: 30
Copy with Modification
Although record
types are immutable, you can create a copy of a record
with some modifications using the with
expression.
var product = new Product("Monitor", 200.00m);
var modifiedProduct = product with { Price = 180.00m };
Console.WriteLine(modifiedProduct.Price); // Prints 180.00
Record Inheritance
record
types also support inheritance, allowing you to create a hierarchy of record
types:
public record Employee(string Name, int Age, string Position) : Person(Name, Age);
In this example, Employee
inherits from Person
and adds an additional property Position
. Inheritance in record
types allows for the reuse of properties and behaviors while maintaining immutability and structural equality.
Pattern Matching
record
types allow the use of pattern matching to compare values and extract data:
public void ShowPerson(Person person)
{
if (person is Person { Age: >= 18 } adult)
{
Console.WriteLine($"{adult.Name} is an adult.");
}
else
{
Console.WriteLine($"{person.Name} is not an adult.");
}
}
In this example, the pattern matching { Age: >= 18 }
checks if the Age
property is greater than or equal to 18 and extracts the instance into an adult
variable if true.