0Pricing
C# Academy · Урок

Типы записей: основы и синтаксис

Объявляйте классы-записи и структуры-записи, разбирайтесь в позиционном синтаксисе и сравнивайте записи с классами.

«Типы записей: основы и синтаксис» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Типы записей: основы и синтаксис
  2. Неизменяемость с init и with
  3. Равенство значений и деконструкция
  4. Записи в предметно-ориентированном проектировании
← Назад к C# Academy