Сборка мусора. Уничтожение объектов.
Распределенная управляемая память автоматически возвращается системе с помощью алгоритма сборки мусора. Общеязыковая среда времени выполнения CLR отслеживает использование памяти, которая выделяется в управляемой ею динамически распределяемой области памяти, и любой участок памяти, на который больше ничто не ссылается, отмечается как "мусор". Когда памяти не хватает, общеязыковая среда времени выполнения CLR просматривает свои структуры данных, с помощью которых она отслеживает использование памяти, и возвращает всю память, помеченную как мусор. Таким образом, программист освобождается от ответственности за освобождение памяти.
Хотя сборка мусора предотвращает утечки памяти в управляемой динамически распределяемой области памяти, она не помогает освобождать другие типы ресурсов. Эти ресурсы включают в себя открытые файлы или соединения с базами данных, а также соединения с сервером, которые должны быть разъединены. Программист должен написать код для явной очистки этих ресурсов. Это можно сделать в деструкторе класса или в специализированном методе для очистки. Общеязыковая среда времени выполнения CLR вызовет этот деструктор для освобождения объекта.
При сборке мусора очень важна эффективность. С автоматической сборкой мусора связаны определенные накладные расходы. Однако общеязыковая среда времени выполнения CLR имеет эффективный алгоритм сборки мусора, учитывающий поколения объектов, участвующих в сборке мусора.
Уничтожение объектов
Исключая ситуацию явного использования оператора delete (уничтожить), для управляемого объекта время разрушения недетерминировано. Деструктор для конкретного объекта, на который нет ссылок, может вызваться в любое время, когда выполняется процесс сборки мусора. Порядок вызовов деструкторов для различных объектов непредсказуем. Более того, при исключительных обстоятельствах деструктор может не вызваться совсем (например, поток войдет в бесконечный цикл или процесс завершится аварийно и тогда во время выполнения не будет возможности провести очистку). К тому же, если оператор delete (уничтожить) не используется явно, то поток, из которого будет вызван деструктор, не определен.
В примере ExplicitDelete демонстрируется, что вызов деструктора является синхронным, и поэтому детерминированным, если явно удалить управляемый указатель. Следующий код демонстрирует создание двух объектов. Первый завершается пассивно путем обнуления указателя на него. Сборщик мусора асинхронно вызывает деструктор в своем собственном потоке. Второй объект разрушается явно с помощью оператора delete (уничтожить) и деструктор вызывается синхронно.
Программа с помощью хэш-кодов отображает подробности того, что случается с каждым объектом, и в каком потоке это случается. Из вывода можно увидеть, что в случае пассивно завершаемого объекта деструктор выполняется в потоке, отличном от того, в котором выполняется функция Main (Главная). И напротив, в случае явного уничтожения объекта деструктор выполняется в том же самом потоке, что и метод Main (Главный).