Да, сборщик мусора освобождает ваши объекты, когда они больше не используются.
То, что мы обычно называем утечкой памяти в .NET, больше похоже на:
- Вы используете внешние ресурсы (которые не являются сборщиком мусора) и забыли освободить их. Обычно это решается путем реализации интерфейса IDisposable.
- Вы думаете, что нет ссылок на данный объект, но на самом деле они есть где-то, и вы их больше не используете, но сборщик мусора не знает о них.
Кроме того, память восстанавливается только при необходимости, то есть сборщик мусора активируется в заданное время и выполняет сбор, определяя, какая память может быть освобождена, и освобождая ее. До тех пор, пока это не произойдет, память не востребована, поэтому может показаться, что память теряется.
Здесь, я думаю, я приведу более сложный ответ только для пояснения.
Сначала сборщик мусора работает в своем собственном потоке. Вы должны понимать, что для восстановления памяти сборщик мусора должен остановить все другие потоки, чтобы он мог отслеживать цепочку ссылок и определять, что зависит от чего. Вот почему память не освобождается сразу, сборщик мусора подразумевает определенные затраты производительности.
Внутренне сборщик мусора управляет памятью в поколениях. В очень упрощенном виде существует несколько поколений долгоживущих, недолговечных и крупногабаритных объектов. Сборщик мусора перемещает объект из одного поколения в другое каждый раз, когда он выполняет сбор, который чаще всего происходит для недолговечного поколения, которое для долгоживущего. Он также перераспределяет объекты, чтобы снова получить максимально возможное непрерывное пространство, поэтому выполнение коллекции - это дорогостоящий процесс.
Если вы действительно хотите увидеть, как вы освобождаете форму (когда вы выходите из области видимости и больше не ссылаетесь на нее), вы можете позвонить GC.Collect()
. Делайте это только для тестирования, крайне неразумно звонить в Collect, за исключением очень немногих случаев, когда вы точно знаете, что делаете, и какие последствия это будет иметь.
Немного подробнее о методе Dispose интерфейса IDispose.
Утилизация не является деструктором обычным способом C ++, она вообще не деструктор. Утилизация - это способ детерминистически избавиться от неуправляемых объектов . Пример. Предположим, вы вызываете внешнюю COM-библиотеку, которая выделяет 1 ГБ памяти из-за того, что она делает. Если у вас нет команды Dispose, память будет сидеть там, тратя пространство до тех пор, пока GC не начнет сборку и не освободит неуправляемую память, вызвав фактический деструктор объекта. Поэтому, если вы хотите сразу освободить память, вам нужно вызвать метод Dispose, но вы не обязаны это делать.
Если вы не используете интерфейс IDisposable, вы должны освободить неуправляемые ресурсы в методе Finalize. Finalize автоматически вызывается из деструктора объекта, когда GC пытается вернуть объект. Так что если у вас есть правильный метод завершения, неуправляемая память будет освобождена в любом случае. Вызов Dispose только сделает его детерминированным.