2011-10-18 11 views
11

He leído mucho sobre el finalizador y IDisposable en C#. Cuando finalmente me despejé de esta monstruosa confusión sobre el finalizador y el IDisposable, de repente, de la nada, surge esta cosa de SafeHandle. Mi creencia está completamente sacudida de nuevo. ¿Qué se supone que debo usar?C# use IDisposable o SafeHandle?

+2

¿Se usa para * qué *, exactamente? –

+0

Use para qué, exactamente. No sé cuál debería usar en qué situación ahora que hay 2 construcciones aparentemente similares. –

+1

@HansPassant Al leer la publicación de MSDN sobre cómo implementar IDisposable, Microsoft presenta dos opciones para implementarlo. Uno está implementando un finalizador, y el recomendado es el uso de un SafeHandle. De hecho, es un poco confuso y engañoso, por lo que puedo entender la pregunta de OP muy bien. URL: http://msdn.microsoft.com/en-us/en-en/library/fs2xkftw%28v=vs.110%29.aspx El sitio web lo hace sonar muy genérico, así que mi primer intento de obtener mi Los objetos de pluma correctamente desechados también estaban con SafeHandle, que no era muy productivo. – Tom

Respuesta

15

SafeHandle solo es útil cuando se trata de llamadas Win32 Interop. En Win32, la mayoría de las cosas están representadas por "identificadores". Esto incluye Windows, Mutexes, etc. Así que .NET SafeHandle usa el patrón desechable para garantizar que el identificador de Win32 se cierre correctamente.

Por lo tanto, si usa las llamadas de interoperabilidad de Win32 y recupera los identificadores de Win32, utilice SafeHandle. Para sus propios objetos, se quedaría con IDisposable y un finalizador.

+0

Pero el objetivo de [IDisposable] (https://msdn.microsoft.com/en-us/library/system.dispositible (v = vs.110) .aspx) es liberar recursos * no administrados *, no es ¿eso? "sus propios objetos" suena ambiguo, ya que el objeto puede representar un objeto administrado * y * no administrado y, como desarrollador usted, puede desarrollar código administrado y no administrado y llamar a su código no administrado desde su código administrado su definición de "propio" también es borroso –

+0

@zespri: si decide implementar IDisposable, eso implica que está manteniendo la clase/objeto (es decir, es el suyo). Si se trata de un objeto de una biblioteca de terceros, no puede implementar IDisposable (es decir, no es suyo). No me estoy refiriendo a lo que se debe eliminar, ni se implementará IDisposable en código no administrado. – CodeNaked

+0

Pero, si se trata de un objeto de una biblioteca de terceros (administrada), ¿no puede implementar 'SafeHandle' tampoco?¿Simplemente porque es probable que no tenga ninguna visibilidad directa del mango en primer lugar de todos modos? Lo siento, no ser combativo, solo trato de entender lo que quieres decir. –

5

Puede/debe usar SafeHandle para cualquier recurso no administrado que pueda representarse como IntPtr, es decir, controladores Win32, memoria asignada por código no administrado, etc. Cuando SafeHandle no es adecuado, pero aún necesita manejar recursos no administrados, considere hacer su propia clase SafeHandle heredando desde CriticalFinalizerObject.

En todos los demás casos (es decir, gestionar recursos gestionados), implemente IDisposable. En la mayoría de los casos, no necesitará el finalizador, la mayoría de los recursos administrados no estarán disponibles cuando se llame al finalizador, por lo que no habría nada que hacer allí.

2

En la mayoría de los casos, mi consejo sería fingir que no existe un finalizador, pero asegúrese al 100% que cualquier objeto IDisposable que se cree se destruya. Incluso si los finalizadores se escriben 100% de manera óptima, el código que elimine la mitad de sus objetos correctamente y permita que los finalizadores manejen la otra mitad no será tan bueno como el código que dispone de todos sus objetos correctamente y no utiliza finalizadores. Si bien es cierto que el impacto en el rendimiento de los finalizadores que normalmente nunca se ejecuta no es demasiado terrible, los finalizadores son difíciles de escribir correctamente, pueden causar heisenbugs si su código o el código que los consume no está escrito a la perfección. Además, la implementación exitosa de finalizadores a menudo requerirá la creación de uno o más WeakHandles, cuyo único propósito es apoyar la finalización.

Tal vez la red de seguridad de finalización vale la pena el costo, pero el costo puede ser considerable y la red de seguridad no es tan confiable como uno podría desear.