Что может храниться в стеке, а что в куче?

Верно ли я понял, что где может храниться?

Я так понял, что в стеке хранятся:

  • Структуры с полями (поля типа значения - в стеке, а поля ссылочного типа - в куче с ссылкой на них в стеке)
  • Ссылки на объекты в куче

А в куче хранятся:

  • Классы с полями и ссылочного, и значимого типа
  • Массивы с элементами и ссылочного, и значимого типа
  • Статические поля и ссылочного, и значимого типа

Ответы (1 шт):

Автор решения: return

Куча в C# — это надстройка над неуправляемой кучей. Её так называют, т.к. там память нужно освобождать вручную (или ждать конца выполнения процесса), в отличие от C#, где память освобождает сборщик мусора (GC).

В C# создали разделение на структуры и классы для оптимизации: классы можно хранить только в куче, а структуры — и там и там. Если вы хотите хранить структуру в куче, вы должны её обернуть (boxing) в объект типа object или реализуемый структурой интерфейс. Пример:

public struct MyStruct : IMyInterface // `IMyInterface` - реализуемый интерфейс
{
    // ...
}
MyStruct @struct = default;
var boxed = (object)@struct; // упаковка в `object`
var @interface = (IMyInterface)@struct; // упаковка в `IMyInterface`

Про GCHandle, Marshal и проч. я рассказывать не буду, т.к. это работа с неуправляемой памятью, что относительно сложно.

Вы также в своём вопросе написали:

А в куче хранятся ... статические поля и ссылочного, и значимого типа.

Это не совсем так. В процессе (в классическом представлении) есть 4 отдела (или, как правильно, сегмента) для хранения памяти:

  • Куча
  • Стек
  • Константы
  • Статическая память

Куча общая, стек — память каждого потока. Память под константы и статическая память идентичны, за одним исключением: константы неизменяемы. Там обычно хранятся большие данные, а маленькие константы (по типу int) просто подставляются (inlining) в то место, где они нужны. Статические данные же изменяемы. Т.е. статические структуры/константы хранятся либо в специальном для этого отделе, либо подставляются.

В данных констант хранятся также строки и массивы с константными данными.

Но вообще, всё это делали реализации и вам не сильно важно, где эти данные хранятся: память в C# управляемая и то, где вы будете хранить данные, выбирает компилятор, давая в некоторых местах свободу действий.

→ Ссылка