Сборщик мусора знает только о памяти. Это хорошо для памяти, потому что один бит памяти почти так же хорош, как и любой другой, при условии, что вам его достаточно. (Это все по модулю кеш-последовательности и т. Д.)
Теперь сравните это с дескрипторами файлов. Операционная система может иметь достаточно места для выделения большего количества дескрипторов файлов, но если вы оставите дескриптор открытым для определенного файла, никто другой не сможет открыть этот конкретный файл для записи. Вы должны сообщить системе, когда закончите с дескриптором, обычно закрывая соответствующий поток, как только закончите, и сделайте так, чтобы он закрывался, даже если выдается исключение. Обычно это делается с помощью оператора using
, который похож на попытку / finally с вызовом Dispose
в блоке finally.
Деструкторы в C ++ очень отличаются от финализаторов .NET, поскольку деструкторы C ++ являются детерминированными - они автоматически вызываются, например, когда соответствующая переменная выходит из области видимости. Финализаторы запускаются сборщиком мусора в некоторый момент после того, как на объект больше не ссылаются какие-либо "живые" объекты, но время непредсказуемо. (В некоторых редких случаях это может никогда не произойти.)
Вы должны реализовать IDisposable
самостоятельно, если у вас есть какая-либо очистка, которая должна быть сделана детерминистически - обычно это происходит, если одна из переменных вашего экземпляра также реализует IDisposable
. В наши дни довольно редко приходится реализовывать финализатор самостоятельно - он обычно нужен только в том случае, если вы держите direct на дескрипторах операционной системы, обычно в виде IntPtr
; SafeHandle
делает все это намного проще и освобождает вас от необходимости писать финализатор самостоятельно.