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

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

Возможно, безопасность финализации стоит затрат, но стоимость может быть значительной, а сеть безопасности не такой надежной, как хотелось бы.