C# использовать IDisposable или SafeHandle?


Я много читал о финализаторе и IDisposable в C#. Когда я, наконец, выхожу из этой чудовищной путаницы с финализатором и IDisposable, внезапно, из ниоткуда, появляется эта безопасная ручка. Моя вера снова полностью поколеблена. Что я должен использовать?

3 11

3 ответа:

SafeHandle полезен только при работе с вызовами взаимодействия Win32. В Win32 большинство вещей представлено "ручками". Это включает в себя окна, мьютексы и т. д. Таким образом, .NET SafeHandle использует одноразовый шаблон, чтобы убедиться, что дескриптор Win32 правильно закрыт.

Поэтому, если вы используете вызовы взаимодействия Win32 и возвращаете дескрипторы Win32, используйте SafeHandle. Для ваших собственных объектов вы бы придерживались IDisposable и финализатора.

Вы можете/должны использовать SafeHandle для любого неуправляемого ресурса, который может быть представлен в виде IntPtr, т. е. дескрипторов Win32, памяти, выделяемой неуправляемым кодом и т. д. Когда SafeHandle не подходит, но вам все еще нужно обрабатывать неуправляемые ресурсы, подумайте о создании собственного класса SafeHandle, наследующего от CriticalFinalizerObject.

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

В большинстве случаев я бы посоветовал сделать вид, что такой вещи, как финализатор, не существует, но сделать 100% уверенным, что любые IDisposable объекты, которые создаются, уничтожаются. Даже если финализаторы написаны на 100% оптимально, код, который правильно распоряжается половиной своих объектов и позволяет финализаторам обрабатывать другую половину, не будет так хорош, как код, который правильно распоряжается всеми своими объектами и не использует финализаторы. Хотя это правда, что на производительность влияют финализаторы, которые никогда не запускаются обычно это не слишком страшно, финализаторы трудно писать правильно, они могут вызвать Хейзенбагс, если их код или код, который их потребляет, написан не идеально. Кроме того, успешная реализация финализаторов часто требует создания одного или нескольких WeakHandles, единственной целью которых является поддержка финализации.

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