2008-10-29 12 views
10

Estoy trabajando en un código de biblioteca alrededor de IDisposable. La ruta administrada (a través de using) es fácilmente comprobable. Sin embargo, me estoy preguntando acerca del finalizador: ¿Es suficiente llamar al System.GC.Collect() para forzar la ejecución del finalizador?¿Cómo puedo probar la unidad? ¿Es descartable?

+0

Si se apega al patrón prescrito para IDisposable, estoy seguro de que la prueba de la unidad va a ser tan útil. –

+0

lo siento, debería haber sido "No estoy seguro de que la unidad de prueba va a ser tan útil ... –

+0

@Mitch: implementar IDisposable correctamente, por lo que los recursos gestionados y no administrados se eliminan en el momento adecuado no es trivial Como el código de la biblioteca en cuestión es responsable de exactamente eso, no veo un punto en _not_ que pruebe ... –

Respuesta

8

No, el GC.Collect() es asíncrono, también tendría que llamar a esto:

System.GC.WaitForPendingFinalizers(); 
+1

¡Muchas gracias! Sabía por qué pregunté :-) –

+1

Creo que GC.Collect() en sí mismo es sincrónico (es decir, habrá liberado cualquier memoria que puede en el momento en que vuelve) pero los finalizadores se ejecutan por separado. Sin embargo, podría estar completamente equivocado ... –

+0

Estoy haciendo las dos cosas ahora y la prueba pasó cada tim mi. Es decir, llamado punto de extensión correcto desde el finalizador. –

0

¿Podrías burlarse de una interfaz IDisposable y esperar una llamada al Dispose? Eso al menos te permitiría ver cuando el objeto está realmente dispuesto.

+0

Establecer un punto de interrupción es suficiente para descubrirlo. Sin embargo, estoy probando la implementación de Dispose(), no si se llama. –

0

creo que me incline hacia la fabricación Finalizar() llamar a otro método, y la prueba de que el otro método hace lo que quiere. No obtendría una cobertura de código del 100%, pero al menos sabría que el método libera los recursos del objeto correctamente.

2

Me gustaría echar un vistazo a Dispose, Finalization, and Resource Management es la mejor referencia sobre el tema que conozco. El uso de su patrón:

~ComplexCleanupBase() 
{ 
    Dispose(false); 
} 

public void Dispose() 
{ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

protected override void Dispose(bool disposing) 
{ 
    if (!disposed) 
    { 
     if (disposing) 
     { 
      // dispose-only, i.e. non-finalizable logic 
     } 

     // new shared cleanup logic 
     disposed = true; 
    } 

    base.Dispose(disposing); 
} 

, terminamos con métodos simples muertos finalizador/Dispose() y un Desechar comprobable (bool). No es necesario forzar la finalización ni nada con la clase GC.

+0

Sí, lo estoy haciendo bastante así. Es solo una pequeña adaptación de lo que se recomienda en MSDN. –

Cuestiones relacionadas