Что занимает меньше памяти: класс или структура в C#?

Ответ

В C# структура (struct) обычно занимает меньше памяти, чем класс (class), из-за различий в их хранении и накладных расходах.

Основные причины:

  1. Размещение в памяти: Экземпляры структур являются значимыми типами (value types). Они хранятся там, где объявлены: в стеке (если это локальная переменная) или внутри родительского объекта (например, как поле класса). Экземпляры классов — ссылочные типы (reference types) — всегда размещаются в управляемой куче, а в стеке или родительском объекте хранится только ссылка на них. Это создает дополнительные накладные расходы.
  2. Накладные расходы кучи: Каждый объект в куче имеет служебный заголовок (указатель на таблицу методов и данные для сборщика мусора), что добавляет минимум 8-16 байт (зависит от разрядности процесса) к размеру данных самого объекта.

Пример:

// Примерный размер: 8 байт (два int по 4 байта)
public struct PointStruct { public int X; public int Y; }

// Примерный размер: 24+ байта.
// Данные: 8 байт (X, Y).
// Накладные расходы кучи: ~16 байт.
// + ссылка на объект в стеке (4/8 байт).
public class PointClass { public int X; public int Y; }

Важные исключения и нюансы:

  • Если структура содержит ссылочные типы (например, string), разница в памяти уменьшается, так как сама ссылка хранится внутри структуры, а данные строки — в куче.
  • Большие структуры (например, > 16 байт) могут быть менее эффективными при передаче в методы по значению, так как происходит полное копирование всех данных. В таких случаях предпочтительнее передавать их по ссылке с модификатором in или использовать класс.
  • Основное правило выбора между struct и class должно основываться на семантике типа (значимый vs. ссылочный), а не только на экономии памяти.

Ответ 18+ 🔞

А, ну это классика, конечно! Смотри, тут всё просто, как три копейки, но с подвохом, как всегда.

Вот представь: структура (struct) — это как будто ты носишь деньги прямо в кармане. Наличка, сразу доступна, никаких тебе банковских операций. А класс (class) — это твоя банковская карта. Сама по себе она кусок пластика, а настоящие деньги где-то там, в банке, и чтобы их потратить, надо ещё через терминал пройти.

Почему структура легче?

  1. Она живёт прямо тут, где родилась. Объявил локальную переменную-структуру — она прямо в стеке и сидит. Сделал её полем в классе — она там же, внутри родительского объекта, как зашитая купюра в подкладку. А экземпляр класса? О, это цирк! Сам объект — в куче (это такая свалка-склад под управлением .NET), а у тебя в руках только бумажка-адресок (ссылка) на него. И за организацию этой свалки тоже надо платить!
  2. Накладные расходы — пиздец. Каждый объект в куче — как чиновник с портфелем. У него обязательная шапка-заголовок (указатель на всякие методы и пометки для сборщика мусора). Это лишние 8-16 байт, которые просто так висят, как галстук на шее. У структуры этого нет, она как работяга в комбинезоне — только то, что нужно для дела.

Смотри, как наглядно:

// Структура. Чистые данные. Два int'а — 8 байт и всё. Никакого геморроя.
public struct PointStruct { public int X; public int Y; }

// Класс. Данные те же — 8 байт. Но плюс:
// 1. Заголовок объекта в куче (~16 байт) — чиновничий портфель.
// 2. Плюс сама ссылка на эту кучу (ещё 4 или 8 байт у тебя в кармане).
// Итого уже под 30 байт выходит, ёпта!
public class PointClass { public int X; public int Y; }

Но, блядь, не всё так радужно, есть же подводные ебли!

  • Если структура зажралась и ссылки таскает. Допустим, внутри неё поле string. Ну, сама-то структура в стеке, а вот строка-то — она в куче! Так что экономия уже не та.
  • Овердохуища большая структура — это проблема. Представь, что твоя структура весит 64 байта. И ты её в метод передаёшь просто так. А она, сука, копируется целиком, все 64 байта! Тут уже хоть в уши себе надуй — производительность летит в пизду. Для таких случаев надо явно передавать по ссылке, через ref или in.
  • Главное — не только памятью думать. Выбор между структурой и классом — это про смысл. Структура — это как DateTime или Point. Простая, маленькая, неделимая величина, которую логично копировать. Класс — это что-то более сложное, с поведением, с идентичностью. Если начнёшь всё пихать в структуры, лишь бы память сэкономить, получишь такую головную боль, что мало не покажется.

Короче, инструменты разные, и тыкать везде struct — это как молотком гвозди и шурупы забивать. Вроде и входит, но потом всё разваливается, блядь. Думай сначала, что делаешь, а потом уже оптимизируй.