Структуры (struct) в C#: объявление и использование

В C# имеются две основные категории типов: value types (значимые типы, например struct) и reference types (ссылочные типы, например class). Поскольку структура — это значимый тип, её поведение ориентировано на хранение данных.
Struct обычно содержит поля и связанные методы. Как правило, они фокусируются на данных, а не на сложном поведении или наследовании.
Как объявить struct
Каждая декларация struct начинается с ключевого слова struct. Перед ним обычно ставят модификатор доступа, затем имя и фигурные скобки. Пример объявления структуры Game:
public struct Game {}Как заполнить struct (поля, конструкторы, методы)
Внутри фигурных скобок struct хранит поля, конструкторы, методы и события. Вот пример структуры с тремя полями, конструктором и переопределением ToString():
public struct Game
{
public string name;
public string description;
public int levels;
public Game(string name, string description, int levels)
{
this.name = name;
this.description = description;
this.levels = levels;
}
public override string ToString() => $"Name: {name}, Description: {description}, Levels: {levels}";
}Этот Game содержит три атрибута, конструктор и метод. Такие компоненты часто совпадают с теми, что используются в классах, но семантика и поведение при копировании отличаются.
Как создать переменную struct (экземпляр)
Экземпляр структуры в C# называют переменной. Есть два подхода.
- Создать через конструктор:
Game game1 = new Game("Pokémon GO", "Короткое описание игры.", 50);- Объявить переменную и присвоить значения полям через точечный оператор:
Game game1;
game1.name = "Pokémon GO";
game1.description = "Короткое описание игры.";
game1.levels = 50;Обе формы приводят к одинаковому результату: переменная game1 теперь содержит данные игры. Вы можете вывести её на консоль так:
Console.WriteLine(game1.ToString());Это выведет:
Name: Pokémon GO, Description: Короткое описание игры., Levels: 50Отличия struct от class
Ключевые различия:
- Семантика копирования: struct — value type. При присвоении копируется вся структура. class — reference type; при присвоении копируется ссылка.
- Наследование: struct не поддерживает (помимо реализации интерфейсов) наследование; class поддерживает.
- Null: переменные struct по умолчанию не могут хранить null (есть Nullable
для разрешения null). Переменные class могут быть null. - Размер и приземлённость: struct хороши для компактных типов (несколько полей). Большие структуры приводят к затратам при копировании.
- Поведение по умолчанию при передаче в методы: для struct — передаётся копия (если не ref/out), для class — передаётся ссылка.
Important: структура — не замена классу везде. Она оптимальна для небольших immutable объектов, например координаты, RGBA‑цвет, значение измерения.
Когда использовать struct, а когда class — руководство
Рекомендуется использовать struct, если все условия верны:
- Тип логически представляет одно значение (например Point, Color, Size).
- Размер небольшой (обычно до нескольких полей; избегайте больших структур из-за расходов на копирование).
- Тип неизменяемый или используется как неизменяемый (immutable) объект.
- Не требуется наследование и nullable‑семантика по умолчанию.
Используйте class, если:
- Нужна полиморфия или наследование.
- Объект большой и дорого копируется.
- Требуется возможность null‑значений без Nullable
. - Нужны общие ссылки на один экземпляр из нескольких мест.
Типичные ошибки и случаи, когда struct не подойдёт
- Хранение больших объёмов данных в struct. Копирование больших структур при присваивании или передаче в методы снижает производительность.
- Ожидание ссылочной семантики (изменение объекта в одном месте должно отражаться в другом). Struct по умолчанию копируется.
- Попытка использовать наследование структуры для повторного использования реализации.
Быстрый чеклист для разработчика
Для выбора struct vs class:
- Нужно ли наследование? Если да — class.
- Нужна ли общая мутируемая сущность? Если да — class.
- Размер объекта небольшой? Если да, struct возможен.
- Объект логически является значением (например координата)? Если да, struct предпочтителен.
Примеры альтернатив и подходов
- Immutable struct: делайте поля readonly и предоставляйте только get‑свойства, чтобы избежать багов, связанных с копированием.
- Records (C# 9+) — хорошая альтернатива для типов-значений с автоматической поддержкой сравнения и неизменяемости (есть record struct и record class).
- Nullable
для разрешения null в struct когда это необходимо.
Критерии приёмки
- Тип компактный и логически представляет значение.
- Нет необходимости в наследовании.
- Тесты проверяют копирование и поведение при передаче параметров по значению и по ссылке.
1‑строчный глоссарий
- struct: значимый (value) тип в C#, копируется при присвоении.
- class: ссылочный (reference) тип в C#, передаётся по ссылке.
- immutable: неизменяемый объект; состояние не меняется после создания.
Краткое резюме
Struct в C# — инструмент для выражения лёгких, семантически «значимых» типов. Он экономит память и упрощает модель данных в правильных сценариях. Выбирайте struct для небольших, неизменяемых значений; используйте class для больших, полиморфных или явно ссылочных сущностей.
Notes: Перед применением struct проверьте паттерны использования в кодовой базе, чтобы избежать неожиданных копирований и проблем с производительностью.
Похожие материалы
Как отключить сенсорный экран Chromebook
Как переназначить клавиши на Chromebook
Call of Duty: WWII — ошибки и исправления
Назначение со‑хоста в Zoom
Как использовать rsync для резервного копирования в Linux