Dispose vs Dispose (bool)

Я смущен насчет распоряжаться. Я пытаюсь правильно использовать ресурсы для моего кода. Поэтому я настраивал свои классы как IDisposable (с помощью метода Dispose), чтобы убедиться, что метод Dispose вызывается.

Но теперь FXCop сообщает мне много информации об Disposing = false и вызове Dispose (false).

Я не вижу метод Dispose, который принимает bool. Нужно ли мне это сделать? Если да, то почему? Почему бы просто не вызвать метод, вызываемый при его утилизации?

Я видел здесь код: http://msdn.microsoft.com/en-us/library/ms244737.aspx, который показывает, как сделать метод Disposing, который принимает bool. В нем говорится, что это для локальных управляемых ресурсов. Но я думал, что весь смысл распоряжения - только для неуправляемых ресурсов.

Кроме того, строка, которую FXCop жалуется, такова:

    ~OwnerDrawnPanel()
    {
        _font.Dispose();
    }

В нем говорится:

CA1063: Microsoft.Design: измените 'OwnerDrawnPanel. ~ OwnerDrawnPanel()', чтобы он вызывал Dispose (false), а затем возвращался.

Но у Font нет Dispose (bool) на нем (что я могу найти).

Подводя итог:

Зачем мне нужен Dispose (bool)? и если да, то почему у Шрифта нет? и поскольку у него его нет, почему FXCop просит меня использовать его?


Спасибо за все замечательные ответы. Думаю, теперь я понимаю. Здесь

Ответ, как я вижу:

Устранение "неуправляемых" ресурсов относится к двум категориям:

  • Ресурсы, которые обернуты в управляемый класс (например, Bitmap, Font и т.д.), но все равно нужно Dispose вызывать для их правильной очистки.
  • Ресурсы, которые вы выделили, которые представляют собой собственные ресурсы (то есть контексты устройства, которые должны быть выпущены)

Dispose (bool) используется для определения разницы между двумя:

  • Когда Dispose непосредственно вызывается на ваш объект, вы хотите освободить оба вида "неуправляемых" ресурсов.
  • Когда ваш объект подходит для коллекции мусора, вам не нужно беспокоиться о первом виде ресурсов. Сборщик мусора позаботится о них, когда он очистит их. Вам нужно только беспокоиться о реальных ресурсах, которые вы выделили (если они есть).

Ответ 1

IDisposable предоставляет метод с сигнатурой

public void Dispose()

Рекомендации Microsoft (http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx) рекомендуют сделать второй закрытый метод с подписью

private void Dispose(bool)

Ваш общедоступный метод Dispose и Finalizer должен вызвать этот частный метод Dispose, чтобы предотвратить одновременное удаление управляемых ресурсов.

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

Ответ 2

Dispose(bool) - это шаблон для реализации Finalize и Dispose для очистки неуправляемых ресурсов, см. это для деталей

Ответ 3

Dispose(bool) не должен быть общедоступным, поэтому вы не видите его на Font.

В случае, если какой-либо пользователь вашего класса забывает вызывать Dispose в своем методе, вы освободите неуправляемые ресурсы только путем вызова Dispose(false) в Finalizer.

В случае, если IDispose вызывается правильно, вы вызываете Dispose на управляемые ресурсы и также заботитесь о неуправляемом.

Флаг должен различать два случая.

Это шаблон, рекомендованный MSDN.

Ответ 4

FxCop говорит, что вы должны реализовать одноразовый шаблон, как описано здесь. Обратите внимание, что вы должны не использовать финализаторы для утилизации управляемых ресурсов, таких как _font. Финализаторы используются для очистки неуправляемых ресурсов. Если вы не выполняете логику очистки в методе Dispose вашего (под) класса, они выполняются недетерминистически сборщиком мусора.

Ответ 5

Также обратите внимание, что очень редко, что вам нужно что-то делать в деструкторе. Регулярно все заботится сборщик мусора. Например, в вашем коде вам не нужно размещать объект _font в деструкторе OwnerDrawnPanel. Поскольку панель очищается GC, так будет _font, потому что панель была единственной, кто ссылался на нее, правильно?

Как правило, если у вас есть одноразовые объекты, вам нужно их уничтожить только при вызове собственного метода Dispose. Но НЕ в деструкторе. Когда ваш деструктор запущен, вы можете поспорить, что все ваши агрегированные объекты также очищаются.

Ответ 6

Вам почти не нужно использовать финализаторы. Они предназначены только для классов, которые непосредственно содержат неуправляемые ресурсы, а в .NET 2.0+ их следует обернуть в SafeHandle.

Ответ 7

Соглашаясь с Kumar, шаблон Dispose(bool disposing) также документируется в MSDN. Различие заключается не в управляемых и неуправляемых ресурсах, а в том, вызывается ли Dispose вашим кодом или временем выполнения.

Ответ 8

Я думаю, что Dispose(true) освободит как управляемый, так и неуправляемый ресурс, так как нам не нужно снова вызывать завершение, потому что мы пишем GC.SupressFinalize() после Dispose(true).

Мы вызываем Dispose(false) в деструкторах для освобождения неуправляемых ресурсов и будем называть Runtime, а не код пользователя.

Ответ 10

Схема реализации публичных финализаторов public void Dispose(), protected virtual void Dispose(bool) и ~ClassName() является наилучшей практикой рекомендованной Microsoft в качестве способ аккуратно организовать ваш код очистки для управляемых и неуправляемых ресурсов.

В принципе, код, который использует ваш класс Disposable, должен вызывать Dispose(), но если это не так, finalizer ~ClassName() будет вызван Garbage Collection, и на основе которого один из них будет использоваться, вы задайте аргумент Dispose(bool) как true или false, а в Dispose(bool) вы очищаете только управляемые ресурсы, если аргумент истинен.

Предупреждение, которое вы получаете, похоже, специально рекомендует использовать эту практику в вашем методе finalize ~ClassName().