C# Стек и Куча. Значимые и ссылочные типы

У каждой переменной есть своё место в области памяти, которой управляет .NET CLR. Объекты живут в куче, локальные переменные в стеке. В чем отличие? Что такое куча? Почему стек?

Если вы не знаете ответы на эти вопросы, то вам сюда :]

Области памяти

CLR управляет памятью в процессе работы программы. Выделим и рассмотрим две области памяти: стек и куча. (мы не будем вдаваться в подробности про низкоуровневые операции)

Последним вошел, первым вышел

Стек – область памяти, которая:

  • Хранит локальные переменные
  • Работает по принципу LIFO (Last In First Out)
  • Строго упорядочен

При вызове метода, CLR помещает переменную в вершину стека, и удаляет её после завершения работы метода.

Пример на котиках

Теперь посмотрим на стек

Возможно, это будет по-капитански, но на вершине стека всегда находятся переменные метода, который исполняется на текущий момент.
После завершения метода Feed() из стека удалится переменная int count, затем Cat cat.

Логово объектов

Куча – это область памяти для хранения объектов, которой управляет сборщик мусора. Получить доступ к объекту можно по ссылке. А ссылка хранится в переменной, которая хранится в стеке.

Значимые и Ссылочные типы

Итак, к значимым типам относятся такие типы как int, bool, decimal ( если заглянуть внутрь, они определены как структуры)
К ссылочным можно отнести объекты. Можно сказать, все то, что наследуется от System.Object.

System.ValueType vs System.Object

Секрет различия значимых и ссылочных типов является следствием их хранения :]
По умолчанию, все аргументы передаются по значению и при присваивании все значения копируются.
Если у нас значимый тип, то копируется его значение. Если это переменная ссылается на объект, копируется ссылка!

Пример на котиках

Результат

В нашей программе, две переменные указывают на один и тот же объект.
Поэтому изменив имя объекта в методе Feed(),  мы изменили один единственные объект, на который ссылается переменнaя musya.
При этом, переменная count остается неизменно равной 4, даже не смотря на то, что мы поменяли значение в методе Feed();

А что если…

Результат

В методе Feed() мы изменили ссылку cat  на другой объект!  Но переменная в методе main все также указывает на старый объект! В этом случае, для того, чтобы изменить ссылку нужно в параметрах метода использовать ref (но это уже отдельный разговор)

Массивы

Массивы относятся к ссылочному типу!

Результат

Мы передали массив в качестве аргумента методу Change() и изменили значение под индексом 0. В результате, мы потеряли значение и теперь нулевой элемент массива равен 10.

Обязательно знайте и помните об этом! Иначе это может привести к неожиданным результатам!!!

А у меня на этом всё. Спасибо за внимание :]

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *