Могут ли объекты ссылочного типа оказаться в стеке?

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

Ответ

Сам объект ссылочного типа (экземпляр класса) всегда размещается в управляемой куче (heap). Однако ссылка (указатель) на этот объект может храниться в стеке (stack). Это важное различие.

Когда ссылка живёт в стеке:

  1. Локальные переменные метода:

    void MyMethod()
    {
        List<string> localList = new List<string>(); // 'localList' - ссылка в стеке
        // Сам объект List<string> находится в куче.
    } // При выходе из метода ссылка 'localList' уничтожается.
  2. Параметры метода, передаваемые по значению:

    void Process(List<string> data) // 'data' - копия ссылки, размещённая в стеке
    {
        data.Add("item"); // Изменяет объект в куче.
    }
  3. Ссылочные локальные переменные и возвращаемые значения (ref, in, out):

    public ref int FindRef(int[] array, int value) // Возвращает ссылку на элемент в куче
    {
        // ... логика поиска
        return ref array[index]; // Возвращается управляемая ссылка.
    }

Исключение: stackalloc С помощью stackalloc можно выделить память в стеке для блока неуправляемой памяти (буфера), но это не управляемый объект ссылочного типа.

Span<int> buffer = stackalloc int[100]; // Память выделена в стеке.

Вывод: Данные объекта — в куче. Адрес этих данных (ссылка) может временно храниться в стеке как локальная переменная или параметр.