Использование деструктора / финализатора дорого? - PullRequest
2 голосов
/ 29 ноября 2010

Я занят, запутавшись в недетерминированном разрушении. В ответ на другой вопрос я получил совет, что деструкторы / финализаторы (которые, как я полагаю, в c # - это то же самое, то есть функция ~ classname ()) являются дорогими и не требуются. Но, глядя на этот пример, используется деструктор, и из комментария звучит так, будто он может быть жизненно важным. Кто-нибудь получил несколько советов о том, как все это сочетается, и мне следует удалить деструктор из моего кода?

Еще раз спасибо.

Ответы [ 3 ]

3 голосов
/ 29 ноября 2010

Вы должны включать финализатор только в том случае, если у вас абсолютно есть для выполнения некоторой очистки в какой-то момент, независимо от того, выполняется оно явно или нет.В таких случаях у вас всегда должен быть явный способ своевременно выполнить очистку, и это в любом случае должно подавлять завершение, чтобы «хорошие» клиенты не видели никакого снижения производительности.

Вы быобычно нужен финализатор, только если у вас есть прямой дескриптор неуправляемых ресурсов - если у вас есть только ссылка на другой класс , который имеет дескриптор ресурса (например, FileStream), тогда вы должны оставить егов другом классе есть финализатор.

С появлением SafeHandle в .NET 2.0 ситуации, когда стоит написать свой собственный финализатор, очень редки .

Снижение производительности финализаторов заключается в том, что они заставляют ваши объекты жить дольше, чем нужно: в первом цикле сборщика мусора, когда они в противном случае считаются подходящими для сбора, они попадают в очередь финализатора - и сталкиваютсядо следующего поколения, как и любой другой объект, который переживает цикл ГХ.Финализатор затем будет запущен в другом потоке (в какой-то момент), и только , тогда они будут иметь право быть действительно собранным.Таким образом, вместо того, чтобы (скажем) собираться в первую коллекцию gen1, они живут прошлым до следующей коллекции gen2 , которая может быть значительно позже.

1 голос
/ 29 ноября 2010

Полный шаблон одноразового использования необходим только при непосредственном взаимодействии с неуправляемым ресурсом. И затем ваш код вызова должен убедиться, что деструктор (почти) никогда не используется.

При работе с управляемыми ресурсами (= косвенное владение неуправляемыми ресурсами) деструктор бесполезен:

class FileWrapper
{
    private FileStream fs;  // managed resource

    ~FileWrapper()
    {
         if (fs != null) 
           fs.Dispose();   // fs is already on the GC finalizer queue
    }
}

Всякий раз, когда GC собирает объект FileWrapper, он уверен, что объект fs находится в том же пакете. Таким образом, вызов fs.Dispose () бесполезен, он проверяет только правильное (допускает несколько вызовов) поведение FileStream.Dispose ().

Единственный полезный деструктор - это FileStream.

1 голос
/ 29 ноября 2010

Обычно реализация деструктора полезна в том случае, если не гарантируется, что клиентский код закроет все ресурсы (файловые потоки, соединения БД и т. Д.) Правильно.Таким образом, если клиентский код не сможет это сделать, у вас будет код, который закроет его, что лучше, чем просто оставить ресурсы открытыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...