Могут ли объекты структур (value-типы) лежать в куче?

«Могут ли объекты структур (value-типы) лежать в куче?» — вопрос из категории Управление памятью, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, структуры (value-типы) часто оказываются в управляемой куче. По умолчанию они размещаются в стеке, но есть несколько распространённых сценариев, приводящих к аллокации в куче:

1. Упаковка (Boxing): При приведении структуры к ссылочному типу (object, ValueType, Enum или интерфейсу).

struct Point { public int X, Y; }
Point p = new Point { X = 5, Y = 10 };
object boxedPoint = p; // УПАКОВКА: 'p' копируется в кучу.
Point unboxedPoint = (Point)boxedPoint; // РАСПАКОВКА: копирование обратно.

2. Структура как поле ссылочного типа:

class Widget // Класс размещается в куче
{
    public Point Location; // Поле-структура будет частью объекта Widget в куче.
}

3. Элемент массива структур:

Point[] points = new Point[100]; // Сам массив (ссылочный тип) в куче.
// Все 100 элементов Point также хранятся в непрерывном блоке памяти внутри массива в куче.

4. Захват в замыкании или лямбда-выражении:

int counter = 0; // Локальная переменная-значение.
Action action = () => Console.WriteLine(counter++); // 'counter' захватывается.
// Компилятор создаёт класс для замыкания, и 'counter' становится его полем (куча).

5. async метод: Локальные переменные в async-методах становятся полями сгенерированного класса состояния, размещаемого в куче.

Практический вывод: Нельзя считать, что структуры всегда в стеке. Их размещение зависит от контекста. Избегайте неявной упаковки в критичных к производительности участках кода.