Dispose vs Dispose (bool) - PullRequest
       27

Dispose vs Dispose (bool)

35 голосов
/ 07 марта 2011

Я смущен по поводу распоряжения. Я пытаюсь получить мой код, правильно распределяющий ресурсы. Поэтому я настраивал свои классы как 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) и затем возвращался.

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

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

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


Спасибо за все великолепные ответы. Я думаю, что теперь понимаю. Вот

Ответ, который я вижу:

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

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

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

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

Ответы [ 10 ]

8 голосов
/ 08 марта 2011

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

7 голосов
/ 08 марта 2011

IDisposable предоставляет метод с подписью

public void Dispose()

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

private void Dispose(bool)

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

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

7 голосов
/ 08 марта 2011

Dispose(bool) не предназначен для публичного доступа, и поэтому вы не видите его на Font.

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

. Если IDispose вызывается правильно, вы вызываете команду Dispose для управляемых ресурсов и позаботьтесь о неуправляемом.

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

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

3 голосов
/ 08 марта 2011

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

2 голосов
/ 26 июня 2011

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

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

2 голосов
/ 08 марта 2011

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

2 голосов
/ 08 марта 2011

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

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

1 голос
/ 08 марта 2011

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

0 голосов
/ 08 марта 2011

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

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

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

0 голосов
/ 08 марта 2011

Я нашел хорошую статью о правильной реализации интерфейса IDispose: http://msdn.microsoft.com/en-us/library/ms244737(v=vs.80).aspx

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