Ответ
Значимые типы (value types) в C# хранятся в стеке потока, когда они объявлены как локальные переменные или параметры метода. Однако это поведение — деталь реализации среды выполнения (CLR), а не гарантия спецификации языка.
Ключевые случаи:
- Локальные переменные внутри метода:
void MyMethod() { int localInt = 42; // Хранится в стеке. DateTime localDate = DateTime.Now; // Struct, хранится в стеке. } - Параметры метода, передаваемые по значению (включая структуры).
Когда значимый тип попадает в кучу:
- Когда он является полем ссылочного типа (класса).
class MyClass { private int _field; // Хранится в куче как часть объекта MyClass. } - При упаковке (boxing), когда значение преобразуется в тип
objectили интерфейс.int number = 10; object boxed = number; // Значение 'number' копируется в кучу. - Когда он является элементом массива.
int[] numbers = new int[10]; // Весь массив, включая элементы, размещается в куче. - При захвате в замыкание или асинхронном методе (локальные переменные становятся полями сгенерированного класса).
Практический совет: Не стоит проектировать код, полагаясь на размещение в стеке для производительности. Фокус должен быть на семантике типа (значимый vs. ссылочный) и корректном управлении временем жизни. Современный CLR и JIT-компилятор могут применять дополнительные оптимизации, например, выделение объектов в стеке (stack allocation), если это безопасно.