Вопрос

Я понимаю, что он используется для освобождения неуправляемых ресурсов, однако я не совсем понимаю, когда фактически вызывается Dispose . Я знаю, что он вызывается в конце блока using , но вызывается ли он и при сборке мусора?

Это было полезно?

Решение

Если вы правильно внедрили IDisposable, вы должны также включить финализатор, который будет вызывать Dispose () для вашего объекта.

Если вы сделаете это, он будет вызван GC. Тем не менее, все равно ОЧЕНЬ хорошая идея всегда пытаться утилизировать эти объекты самостоятельно.

Самая большая проблема при использовании финализатора для вызова Dispose заключается в том, что это произойдет в другом потоке, который вы не контролируете. Это может иметь неприятные последствия в определенных ситуациях, в том числе вызывать исключение, которое происходит в потоке GC, что не очень хорошо, а также иметь выбранное поле, которое вы проверяете. Это также часть того, почему важно включить GC.SuppressFinalize (this) в ваш метод Dispose () - после удаления объекта вы не хотите его повторно размещать.

Другие советы

Утилизация вызывается в нескольких местах:

<Ол>
  • В конце использования блока.
  • При явном вызове (например, в try {} finally {}.)
  • Рекомендуется называть его самостоятельно, когда вы закончили с ресурсом, чтобы лучше управлять ресурсами.

    РЕДАКТИРОВАТЬ: я ошибся. Утилизация НЕ вызывается во время сбора мусора. См. эта статья.

    Нет, он не вызывается при сборке мусора. Если вам нужно такое поведение, вы можете использовать деструктор (финализатор) и вызов Dispose () оттуда.

    Как вы говорите, он вызывается автоматически и заканчивается блоком using .

    Dispose () вызывается в конце блока Using, чтобы вы могли рассчитывать на действия Dispose (например, закрытие соединения БД), которые будут выполняться, когда объект выходит из области видимости. Все просто.

    Обновление: в вызове Dispose нет ничего специфичного для неуправляемых ресурсов (хотя это обычное использование).

    Обновление 2 : по теме, которую начал Рид Копси, ведутся споры, полезные для понимания IDisposable. Я настоятельно рекомендую эту статью людям, желающим узнать больше.

    В двух словах, класс IDisposable позволяет вам явно обрабатывать освобождение ресурсов (обычно неуправляемых ресурсов или соединений с базой данных) с помощью метода Dispose (). Экземпляры IDisposable класса должны быть созданы в " Использование " блок, чтобы гарантировать, что метод Dispose действительно вызывается. Если вам не удастся сделать это (или явно вызвать его в блоке «finally» и т. Д.), То ваш метод Dispose не будет вызван, и вы потеряете объекты, которые хотите очистить. В всех случаях я помещаю одноразовые классы в блоки Using, и вы тоже должны.

    В качестве альтернативы вы можете выполнить очистку ресурсов в Финализаторе (класс Destructor). Это будет вызвано автоматически, когда класс GC'd. Недостатки этого подхода состоят в том, что вы не будете явно контролировать , когда объекты очищаются, и есть некоторые проблемы с многопоточностью, с которыми приходится сталкиваться. Так, например, проблемы в деструкторах очень трудно отлаживать из-за того, что они вызываются асинхронно и в другом потоке. Единственное преимущество заключается в том, что вам не нужно не забывать звонить своему деструктору, как вы это делаете. Конечно, если вы всегда используете «Использование блоков», это не проблема.

    ПРИМЕЧАНИЕ. Я, ktrauberman, Reed и Pontus, сделал несколько хороших замечаний о том, как вы можете обойти те моменты, которые я делаю ниже. Это то, что я делаю, но я не могу утверждать, что это единственный способ сделать что-то. Действительно, Microsoft даже рекомендует в некоторых случаях вызывать Dispose () из финализатора. Тем не менее, я оставлю обсуждение здесь просто как иллюстрацию того, почему важно следовать совету Рида относительно осторожности при смешивании Destructors и Dispose ().

    Я не согласен с ответом Рида в том, что вам следует реализовать класс IDisposable, вызвав Dispose () в вашем Финализаторе. Это просто объединяет две разные конструкции и может привести к проблемам. Например, если вы создадите свой экземпляр класса IDisposable в блоке Using и и вызовете Dispose () в Destructor, он будет вызван дважды - с потенциально неприятными и трудными для отладки сбоями (опять же, вы не контролируйте время GC). (Примечание: это действительно относится к деструкторам в целом - при определенных обстоятельствах их можно вызывать более одного раза!)

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top