Что может храниться в стеке, а что в куче?
Верно ли я понял, что где может храниться?
Я так понял, что в стеке хранятся:
- Структуры с полями (поля типа значения - в стеке, а поля ссылочного типа - в куче с ссылкой на них в стеке)
- Ссылки на объекты в куче
А в куче хранятся:
- Классы с полями и ссылочного, и значимого типа
- Массивы с элементами и ссылочного, и значимого типа
- Статические поля и ссылочного, и значимого типа
Ответы (1 шт):
Куча в 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# управляемая и то, где вы будете хранить данные, выбирает компилятор, давая в некоторых местах свободу действий.