Типы записей: основы и синтаксис
Объявляйте классы-записи и структуры-записи, разбирайтесь в позиционном синтаксисе и сравнивайте записи с классами.
«Типы записей: основы и синтаксис» — бесплатный урок C# Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Что такое типы записей
Записи (появившиеся в C# 9) — это ссылочные типы, предназначенные для неизменяемых данных с семантикой значения. Они автоматически создают равенство на основе значений свойств, удобочитаемый ToString() и поддерживают создание изменённых копий с помощью выражений with.
Позиционный синтаксис записей
Позиционный синтаксис — самая краткая форма объявления. Свойства, конструктор, деконструирование и равенство создаются автоматически на основе одной строки.
// All in one line:
public record Point(double X, double Y);
public record Person(string FirstName, string LastName, int Age);
// Generated automatically:
// - Primary constructor: new Point(1.0, 2.0)
// - Deconstruct: var (x, y) = point;
// - Equality: p1 == p2 compares X and Y values
// - ToString: "Point { X = 1, Y = 2 }"Записи и классы
Записи и классы отличаются главным образом равенством по умолчанию и назначением. Записи используют структурное равенство (значения), а классы — ссылочное равенство (идентичность).
var p1 = new Point(1, 2);
var p2 = new Point(1, 2);
var p3 = p1;
// Record: structural equality
Console.WriteLine(p1 == p2); // True — same values
Console.WriteLine(p1 == p3); // True — same values
// Compare with a class:
var c1 = new PointClass(1, 2);
var c2 = new PointClass(1, 2);
Console.WriteLine(c1 == c2); // False — different referencesСтруктуры-записи
C# 10 добавляет record struct — записи-значения. У них те же возможности равенства и ToString, что и у классов-записей, но они размещаются в стеке, как структуры.
// Record struct: value type, stack-allocated
public record struct Color(byte R, byte G, byte B);
var red = new Color(255, 0, 0);
var red2 = new Color(255, 0, 0);
Console.WriteLine(red == red2); // True — value equality
// Readonly record struct: fully immutable
public readonly record struct Coord(double Lat, double Lng);Стандартное объявление записи с телом
Записи могут иметь полноценное тело: в нём можно добавлять вычисляемые свойства, методы и проверку в конструкторе, сохраняя автоматические равенство и ToString.
public record Person(string FirstName, string LastName)
{
// Computed property
public string FullName => $"{FirstName} {LastName}";
// Validation in constructor
public Person : this(FirstName, LastName)
{
if (string.IsNullOrWhiteSpace(FirstName))
throw new ArgumentException("FirstName required");
}
// Method
public Person WithUpperCase() =>
this with { FirstName = FirstName.ToUpper(), LastName = LastName.ToUpper() };
}Наследование записей
Записи поддерживают наследование. Производная запись добавляет свойства и участвует в тех же правилах равенства: две записи равны только тогда, когда совпадают их типы и все значения.
public record Shape(string Color);
public record Circle(string Color, double Radius) : Shape(Color);
public record Rectangle(string Color, double Width, double Height) : Shape(Color);
var c1 = new Circle("red", 5.0);
var c2 = new Circle("red", 5.0);
var r1 = new Rectangle("red", 5.0, 3.0);
Console.WriteLine(c1 == c2); // True
Console.WriteLine(c1 == r1); // False — different typesНепозиционные свойства записей
Записи не ограничены позиционными параметрами. Можно сочетать позиционные и заданные вручную свойства, а также использовать инициализаторы свойств для задания значений по умолчанию.
public record Order
{
public int Id { get; init; }
public string CustomerName { get; init; } = "";
public List<OrderLine> Lines { get; init; } = new();
public DateTime CreatedAt { get; init; } = DateTime.UtcNow;
public OrderStatus Status { get; init; } = OrderStatus.Pending;
}
// Initialization:
var order = new Order
{
Id = 42,
CustomerName = "Alice"
// Other props use defaults
};Деконструирование
Позиционные записи автоматически создают метод Deconstruct, благодаря чему их можно разобрать на составляющие при присваивании и сопоставлении с образцом.
public record Point(double X, double Y);
var p = new Point(3.0, 4.0);
// Deconstruction
var (x, y) = p;
Console.WriteLine($"x={x}, y={y}");
// In switch:
string Describe(Point pt) => pt switch
{
(0, 0) => "Origin",
(double x, 0) => $"On X-axis at {x}",
(0, double y) => $"On Y-axis at {y}",
var (px, py) => $"Point ({px}, {py})"
};Записи как DTO
Записи отлично подходят для объектов передачи данных (DTO) запросов и ответов API. Они неизменяемы, поддерживают сериализацию, а автоматически создаваемое равенство упрощает написание тестов.
// API request/response records
public record CreateProductRequest(
string Name,
decimal Price,
int Stock);
public record ProductResponse(
int Id,
string Name,
decimal Price,
int Stock,
DateTime CreatedAt);
// In controller:
app.MapPost("/products", (CreateProductRequest req, ProductService svc) =>
{
var product = svc.Create(req.Name, req.Price, req.Stock);
return Results.Created($"/products/{product.Id}",
new ProductResponse(product.Id, product.Name,
product.Price, product.Stock,
product.CreatedAt));
});Равенство записей в модульных тестах
Равенство по значению делает записи идеальными для утверждений в модульных тестах. Можно сравнивать ожидаемые и фактические записи с помощью == или Assert.Equal без специальных компараторов.
[Fact]
public async Task CreateOrder_ReturnsCorrectResponse()
{
var response = await _client.PostAsJsonAsync("/orders",
new CreateOrderRequest(CustomerId: 1, ProductId: 5, Quantity: 2));
var order = await response.Content.ReadFromJsonAsync<OrderResponse>();
// Simple equality check — no custom IEqualityComparer needed!
Assert.Equal(
new OrderResponse(Id: order!.Id, Status: "Pending", Total: 99.98m),
order);
}Быстрая проверка
Какую семантику равенства используют записи C# по умолчанию?
Повторение: основы типов записей
Основные выводы:
- Записи по умолчанию являются ссылочными типами со структурным равенством по значению
- Позиционный синтаксис создаёт конструктор, деконструирование, равенство и ToString
record struct(C# 10) — вариант типа-значения- Записи поддерживают наследование — для равенства должен совпадать и тип
- Они отлично подходят для DTO, контрактов API и утверждений в модульных тестах
- В блоке тела можно добавлять вычисляемые свойства и методы вместе с позиционными параметрами
Часто задаваемые вопросы
Урок «Типы записей: основы и синтаксис» бесплатный?
Да — полный текст урока «Типы записей: основы и синтаксис» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «Типы записей: основы и синтаксис»?
Объявляйте классы-записи и структуры-записи, разбирайтесь в позиционном синтаксисе и сравнивайте записи с классами. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Типы записей: основы и синтаксис»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Типы записей: основы и синтаксис
- Неизменяемость с init и with
- Равенство значений и деконструкция
- Записи в предметно-ориентированном проектировании