What is Record Keyword/Function in C#?

Introduction

A record in C# is a class or struct that provides special syntax and behavior for working with data models. The record modifier instructs the compiler to synthesize members that are useful for types whose primary role is storing data. These members include an overload of ToString() and members that support value equality.

Records introduced in C# 9.0 represent a significant enhancement to the language's capability for handling data. They provide a concise syntax for defining immutable data types, promoting immutability, and value semantics. This article aims to explore records in-depth, covering their syntax, features, and usage through illustrative examples.

When to use records?

Consider using a record in place of a class or struct in the following scenarios:

  • You want to define a data model that depends on value equality.
  • You want to define a type for which objects are immutable.

Syntax of Records

Declaring a record in C# involves using the record keyword followed by the name of the record and its properties enclosed within parentheses. Here's the basic syntax:

public record Person(string FirstName, string LastName, int Age);

In this example, Person is a record with three properties: FirstName, LastName, and Age. Records can include any number of properties, and each property is implicitly read-only.

Key Features of Records

  1. Immutability by Default: Records are immutable by default, meaning once created, their properties cannot be modified. This ensures data integrity and eliminates the risk of unintended changes.
  2. Value Equality: Records support value equality out of the box. Two record instances are considered equal if all their properties have equal values. This simplifies comparison operations and makes records suitable for use in collections like dictionaries and sets.
  3. Concise Syntax: Records provide a concise syntax for declaring data types, reducing boilerplate code. Properties can be declared directly within the record declaration, making the code more readable and maintainable.
  4. Inheritance: Records support inheritance, allowing you to create derived record types with additional properties or behavior. This enables code reuse and facilitates polymorphic behavior.
  5. With-Expressions: Records support with-expressions, which enable the creation of new record instances with modified properties while preserving the original instance's values. With-expressions provide a convenient way to update records without mutating them.

Examples of Records

Let's explore some examples to illustrate the usage of records in C#:

Example 1. Basic Record

public record Person(string FirstName, string LastName, int Age);

var person1 = new Person("John", "Doe", 30);
var person2 = new Person("Jane", "Smith", 25);

Console.WriteLine(person1.Equals(person2)); // Output: False

In this example, we define a Person record with three properties: FirstName, LastName, and Age. We then create two Person instances and check their equality using the Equals method, which returns false because their properties differ.

Example 2. Record Inheritance

public record Employee : Person
{
    public string Department { get; init; }

    public Employee(string firstName, string lastName, int age, string department)
        : base(firstName, lastName, age)
    {
        Department = department;
    }
}

var employee = new Employee("John", "Doe", 30, "IT");

In this example, we define an Employee record that inherits from the Person record. The Employee record includes an additional property, Department. We then create an Employee instance and initialize its properties using the constructor.

Example 3. With-Expressions

var updatedEmployee = employee with { Age = 31 };

Here, we use a with-expression to create a new Employee instance based on the existing employee instance with the Age property modified to 31. The with keyword creates a new instance with the specified changes while leaving the original instance unchanged.

How do records differ from classes and structs?

The same syntax that declares and instantiates classes or structs can be used with records. Just substitute the class keyword with the record, or use record struct instead of struct. Likewise, the same syntax for expressing inheritance relationships is supported by record classes. Records differ from classes in the following ways:

  • You can use positional parameters in a primary constructor to create and instantiate a type with immutable properties.
  • The same methods and operators that indicate reference equality or inequality in classes (such as Object.Equals(Object) and ==) indicate value equality or inequality in records.
  • You can use a with expression to create a copy of an immutable object with new values in selected properties.
  • A record's ToString method creates a formatted string that shows an object's type name and the names and values of all its public properties.
  • A record can inherit from another record. A record can't inherit from a class, and a class can't inherit from a record.

Record structs differ from structs in that the compiler synthesizes the methods for equality and ToString. The compiler synthesizes a Deconstruct method for positional record structs.

The compiler synthesizes a public init-only property for each primary constructor parameter in a record class. In a record struct, the compiler synthesizes a public read-write property. The compiler doesn't create properties for primary constructor parameters in class and struct types that don't include record modifiers.

Conclusion

Records in C# provide a powerful mechanism for defining immutable data types with value semantics. Their concise syntax, support for inheritance, and built-in immutability make them ideal for representing data structures in applications. By leveraging records, developers can write cleaner, more maintainable code that is less prone to bugs and easier to reason about.

Records represent a significant enhancement to C#'s capabilities, offering a modern approach to data modeling and manipulation. As you continue to explore C# development, consider incorporating records into your projects to benefit from their simplicity and efficiency.

References


Similar Articles