Это старый вопрос, который я знаю, но я проводил некоторые исследования утечек ресурсов, связанных с объектами GDI, и почти каждое утверждение в принятом ответе ложно.В интересах точности для более поздних читателей, которые находят этот вопрос с помощью поиска, как я сделал:
Нет необходимости вызывать Dispose.
Это утверждение вводит в заблуждение.Хотя технически вы можете обойтись без звонка Dispose
, крайне плохая практика - не выбрасывать кисть или ручку , которыми вы владеете , когда закончите с ней.
Причина в том, что существует жесткое ограничение (установленное по умолчанию на десять тысяч, хотя оно может быть увеличено с помощью взломов реестра) количества объектов GDI, которые могут быть выдающимися в процессе - не в домене приложения, а в примечании - исборщик мусора может не успеть доработать ресурсы быстрее, чем они просочились.Распределение управляемой памяти создает давление сбора , но соответствующее давление завершения отсутствует.
Целью сбора мусора является устранение подобных требований.
Это не так.Целью сбора мусора является эмуляция среды с произвольно большим объемом памяти.
Одна из основных целей IDisposable
- позволить классу очищать неуправляемые ресурсы в средах с ограниченными ресурсами.
Это правильно.
Если не вызывать метод Dispose()
, неуправляемые ресурсы класса будут очищены после того, как объект будет завершен и удаленво время сбора мусора.
Это иногда правильно;это верно для объектов GDI.Это хорошая практика для классов, которые держатся за неуправляемые ресурсы, для реализации семантики финализации в качестве поддержки;дополнительный уровень защиты для людей, которые следуют плохим советам, данным в принятом ответе. Вы не должны полагаться на финализаторы, чтобы спасти вас от ваших ошибок;Вы должны распоряжаться своими ресурсами.
Вы должны полагаться только на финализатор, чтобы справляться с безумными исключительными ситуациями.Рассмотрим для примера:
Brush myBrush = MakeMeABrush();
DoSomethingWithBrush(myBrush);
myBrush.Dispose();
Предположим, что исключение прерывания потока генерируется после выделения кисти, но до назначения myBrush.Никакая комбинация try-catch-finally
не позволит вам очистить эту кисть с помощью Dispose
;вам придется положиться на финализатор.Вот для чего нужен финализатор: совершенно сумасшедшие ситуации, когда вы не можете распоряжаться собой. Это не повод быть небрежным.
Если вы "должны" вызвать dispose, и вы не знаете, является ли экземпляр кисти "системным" или "нормальным"- "кисть, тогда вам придется использовать блок try ... catch.
Хотя это опять-таки технически правильно, оно полностью упускает смысл. Если вы находитесь в ситуации, когда вы не знаете, владеете ли вы кистью или нет, у вас есть ошибка в дизайне вашей программы .Не печатайте на своих ошибках с try-catch
блоком!Исправьте ошибку!
Эта ситуация является общей для всех явно управляемых ресурсов: сущность, которая предоставляет ресурс, и сущность, которая потребляет ресурс, ответственны за четкое документирование того, кто из двух владеет очисткойресурс .Если вы не знаете, являетесь ли вы владельцем кисти, которую вам дали, или нет, тогда кто-то не выполняет задачу, за которую он должен был выполнить , а именно , предотвращая возникновение этой ситуации..
Если договор, по которому вы решаете, заключается в том, что организация, предоставляющая ресурс, несет ответственность за его очистку позднее, то ваш потребитель вообще не должен утилизировать щетку , потому что эторазрыв контракта;продюсер очистит это, если потребуется.
Если договор, по которому вы принимаете решение, заключается в том, что как производитель, так и потребитель собираются освободить ресурс, потребитель должен вызвать Clone
на каждую кисть, переданную, чтобы убедиться, что у него есть одноразовый сейф.ресурс, и что производитель продолжает владеть действительным ресурсом.
Если, скорее всего, договор, по которому вы решите, заключается в том, что организация, потребляющая ресурс, несет ответственность за его очистку позже, чем провайдер обязан всегда вручать вам кисть, которую вы можете безопасно утилизировать , и , а не распоряжаться самим ресурсом.Поскольку поставщик знает, сделали ли они кисть самостоятельно или получили ее из системы, поставщик должен вызвать Clone()
на системных щетках, чтобы получить кисть, которую можно безопасно утилизировать, а затем передать , что потребителю.
Но контракт «никто не убирает его, и мы надеемся на лучшее» - довольно плохой контракт.
Не нужно звонить Dispose()
на SystemBrushes
и SystemPens
, поскольку библиотека GDI + позаботится об этих ресурсах.
Это объяснение является объяснением, которое фактически ничего не объясняет.Причина, по которой нельзя утилизировать одну из этих кистей, заключается в том, что время жизни кисти равно времени жизни домена приложения .
Раздел «Замечания» классаотметит, если есть требование для вызова метода Dispose.
Это утверждение неверно.Вы должны исходить из предположения, что ресурс Dispose
IDisposable
всегда необходим, если у вас нет веских оснований полагать иначе.Отсутствие строки в документации не является доказательством того, что утилизация не нужна.
В заключение положительная нота:
Если у меня есть приложение или класс с интенсивным графическим интерфейсом, тогда ябудет кэшировать экземпляры ручек и кистей, которые мне нужны.Я использую их на протяжении всей жизни приложения или класса.
Это хорошая практика.Если количество созданных кистей и ручек относительно невелико и одни и те же используются снова и снова, то имеет смысл постоянно их кэшировать.Поскольку их время жизни подходит к концу программы, нет необходимости распоряжаться ими.В этом случае мы не выбрасываем мусор, потому что это не мусор ;это полезноОбъекты GDI, которые не кэшированы, должны, конечно, все еще располагаться.Опять же, следование стратегии кэширования не является оправданием для использования плохих практик.