В чем разница по объему и управлению памятью между стеком (stack) и кучей (heap) в .NET?

Ответ

Разница фундаментальна и касается выделения, времени жизни и размера памяти.

Характеристика Стек (Stack) Куча (Heap)
Что хранится Значимые типы (Value Types): int, bool, struct, а также ссылки на объекты в куче. Ссылочные типы (Reference Types): экземпляры class, массивы, строки (string).
Управление памятью Автоматическое, по LIFO. Память освобождается мгновенно при выходе из области видимости (метода). Крайне быстро. Управляется сборщиком мусора (GC). Память освобождается не сразу, а когда GC решит, что объект больше не нужен. Это создает паузы.
Скорость выделения Очень высокая. Просто сдвигается указатель стека. Относительно ниже. Требуется поиск свободного блока и синхронизация потоков.
Размер Ограничен (обычно ~1 МБ на поток по умолчанию в .NET). Превышение приводит к StackOverflowException. Огромен. Ограничен только доступной виртуальной памятью ОС.
Фрагментация Нет. Возможна. GC проводит компрессию (уплотнение) для ее борьбы.

Практический пример и важные нюансы:

void Example()
{
    int number = 42;          // Значимый тип 'int' размещается в СТЕКЕ.
    object obj = new object(); // 1. Экземпляр 'object' создается в КУЧЕ.
                               // 2. Ссылка 'obj' (адрес в памяти) размещается в СТЕКЕ.
} // При выходе из метода:
  // - 'number' и ссылка 'obj' автоматически удаляются из стека.
  // - Сам объект в куче помечается для будущей сборки мусора.

Ключевые исключения (где value type может оказаться в куче):

  1. Упаковка (Boxing): int i = 10; object boxed = i;
  2. Поля ссылочного типа: Поле int внутри class хранится в куче вместе с экземпляром класса.
  3. Захват в замыкании или асинхронном методе.
  4. Большие структуры могут быть неявно размещены в куче для оптимизации производительности.

Ответ 18+ 🔞

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

Представь себе, что стек — это как твой рабочий стол. Ты на него кладёшь бумажки, которые нужны прямо сейчас: счёт за квартиру, список покупок, паспорт. Всё под рукой, всё быстро берёшь и быстро убираешь, как только дело сделано. Вот так и стек работает: закинул туда переменную int number = 42 — она тут же под рукой. Вышел из метода — и всё, стол чист, память свободна. Быстро, чётко, но места мало. Перегрузишь стол — и всё, пиздец, StackOverflowException, всё летит нахуй.

А куча — это уже как гараж или подвал. Туда ты тащишь всё, что громоздкое и нужно надолго: старый диван, велосипед, коробки с хернёй. Выделил место под объект new object() — и он там лежит, пока не приедет сборщик мусора (это такой грузчик-алкаш, который приходит не по расписанию, а когда захочет). Он посмотрит, пользуешься ты этим диваном или нет, и если нет — выкинет на свалку. Места в гараже дохуя, но чтобы что-то найти или выкинуть, времени уходит больше.

Вот смотри на примере, чтобы вообще всё встало на свои места:

void Example()
{
    int number = 42;          // Это как записка на столе (стек). Быстро написал, быстро выкинул.
    object obj = new object(); // А вот это уже диван. 1. Сам диван (объект) тащишь в гараж (кучу).
                               // 2. А записку с адресом гаража, где диван стоит, кладёшь на стол (ссылку `obj` в стек).
} // Выходишь из комнаты (метода) — и что? Записку со стола выкинул сразу.
  // А диван в гараже так и стоит, пока тот алкаш-грузчик не соизволит его вынести.

И да, есть подлянка, про которую все забывают. Иногда твоя записка со стола (значимый тип) вдруг оказывается в гараже. Как так? Да очень просто!

  1. Упаковка (Boxing). Это когда ты свою записку (int i = 10) ради важности засовываешь в коробку (object boxed = i) и тащишь эту коробку уже в гараж. Зачем? Ну, бывает нужно. Глупо, неэффективно, но иногда без этого никуда.
  2. Поле в классе. Если твой int — это не просто записка, а деталь от того самого дивана (поле внутри класса), то понятное дело, он будет валяться в гараже вместе со всем диваном.
  3. Захватили в лямбду или async. Это когда ты про свою записку на столе кому-то рассказал, а она тебе потом ещё долго и нудно нужна. Чтобы не потерялась, её тоже отправляют в гараж на сохранение.
  4. Структура большая. Если твоя «записка» — это целый рулон обоев (большая структура), то её на стол и не положить — только в гараж. Система сама это сделает, чтобы не ебаться.

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