Record: современный способ описания данных в C#

Все, кто работает с объектно-ориентированными языками высокого уровня, знают, что базовый способ описания типа — class (такое название есть и C#, и в C++, и в Kotlin, и в Python). Обычно объект создаётся в динамической памяти (heap).

Для небольших объектов и оптимизации работы с памятью в семье C#/C++ есть struct. Этот тип объекта создается в стэке, копирование и сравнение по значению, наследование не поддерживается.

И вот, сравнительно недавно (во времена КОВИДа, версия C# 9) появилась ещё одна сущность для описания данных — record.

На самом деле, такая работа с данными существует давно, но в языке теперь имеется простой способ описания, «синтаксический сахар».

Его основные преимущества:

  • Неизменяемость (immutable) по умолчанию — значения задаются при создании.
  • Сравнение по значению — объекты считаются равными, если все их поля совпадают.
  • Лёгкое копирование с изменением через with.
  • Подходит для DTO (data transfer object), конфигураций, событий, фильтров и других объектов данных.

Выглядит это так:

record UserDto(string Name, string Email, int Age); // здесь мы описываем тип, как class или struct

var user1 = new UserDto("Alice", "alice@example.com", 30); // здесь делаем неизменную сущность
var user2 = user1 with { Age = 31 }; // новый объект, оригинал не меняется


Это полезно для хранения данных, без лишних копий (а Вы наверняка сталкивались с необходимостью следить, не создалось ли у Вас в памяти очень много объектов после манипуляции с данными).

Например,

— можно хранить настройки неизменными:

record AppSettings(string Theme, int MaxItems);

var settings = new AppSettings("Dark", 100);
var updatedSettings = settings with { MaxItems = 200 };


— создавать события и сообщения:

record OrderPlaced(int OrderId, string Customer, decimal Amount);

var evt = new OrderPlaced(123, "Bob", 99.99m);


— создавать легкие для сравнения объекты:

record Filter(string Field, string Value);

var f1 = new Filter("Name", "Alice");
var f2 = new Filter("Name", "Alice");

Console.WriteLine(f1 == f2); // true — сравнение по значению
// никаих Equals, GetHashCode etc.

Итак, вот главное различие с struct и class:

CLASS: Копирование по ссылке, сравнение по ссылке, мутабельность: mutable, наследование: есть.

STRUCT: Копирование по значению, сравнение по значению, мутабельность: mutable, или readonly, наследование: нет.

RECORD: Копирование по значению, сравнение по ссылке, мутабельность: immutable, наследование: нет.


Надеюсь, пригодится это знакомство с record, если это новое для Вас 🙂

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *