Ответ
Сам объект ссылочного типа (экземпляр класса) всегда размещается в управляемой куче (heap). Однако ссылка (указатель) на этот объект может храниться в стеке (stack). Это важное различие.
Когда ссылка живёт в стеке:
-
Локальные переменные метода:
void MyMethod() { List<string> localList = new List<string>(); // 'localList' - ссылка в стеке // Сам объект List<string> находится в куче. } // При выходе из метода ссылка 'localList' уничтожается. -
Параметры метода, передаваемые по значению:
void Process(List<string> data) // 'data' - копия ссылки, размещённая в стеке { data.Add("item"); // Изменяет объект в куче. } -
Ссылочные локальные переменные и возвращаемые значения (
ref,in,out):public ref int FindRef(int[] array, int value) // Возвращает ссылку на элемент в куче { // ... логика поиска return ref array[index]; // Возвращается управляемая ссылка. }
Исключение: stackalloc
С помощью stackalloc можно выделить память в стеке для блока неуправляемой памяти (буфера), но это не управляемый объект ссылочного типа.
Span<int> buffer = stackalloc int[100]; // Память выделена в стеке.
Вывод: Данные объекта — в куче. Адрес этих данных (ссылка) может временно храниться в стеке как локальная переменная или параметр.