Tengo el siguiente código
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
El dispose()
método se llama al final de las using
llaves de declaración, }
¿verdad? Dado que return
antes del final de la using
declaración, ¿el MemoryStream
objeto se eliminará correctamente? ¿Qué pasa aquí?
Respuestas:
Sí,
Dispose
se llamará. Se llama tan pronto como la ejecución abandona el alcance delusing
bloque, independientemente de los medios que tomó para abandonar el bloque, ya sea el final de la ejecución del bloque, unareturn
declaración o una excepción.Como @Noldorin señala correctamente, el uso de un
using
bloque en el código se compila entry
/finally
, con laDispose
llamada en elfinally
bloque. Por ejemplo, el siguiente código:efectivamente se convierte en:
Por lo tanto, porque
finally
se garantiza que se ejecutará después de que eltry
bloque haya finalizado la ejecución, independientemente de su ruta de ejecución,Dispose
se garantiza que se llamará, pase lo que pase.Para obtener más información, consulte este artículo de MSDN .
Apéndice:
Solo una pequeña advertencia para agregar: debido a que
Dispose
se garantiza que se llamará, casi siempre es una buena idea asegurarse de queDispose
nunca se produzca una excepción cuando se implementaIDisposable
. Por desgracia, hay algunas clases en la biblioteca central que hacen un tiro en ciertas circunstancias cuandoDispose
se llama - que estoy mirando a ti, proxy de servicio WCF Referencia / cliente! - y cuando eso sucede, puede ser muy difícil rastrear la excepción original siDispose
se llamó durante un desenrollado de la pila de excepciones, ya que la excepción original se traga a favor de la nueva excepción generada por laDispose
llamada. Puede resultar tremendamente frustrante. ¿O es eso frustrantemente enloquecedor? Uno de los dos. Tal vez ambos.fuente
Dispose
finalmente, por lo que está funcionando efectivamente con la implementación definally
, como usted describe.using
Las declaraciones se comportan exactamente comotry ... finally
bloques, por lo que siempre se ejecutarán en cualquier ruta de salida de código. Sin embargo, creo que están sujetos a muy pocas y raras situaciones en las quefinally
no se llaman bloques. Un ejemplo que puedo recordar es si el subproceso en primer plano sale mientras los subprocesos en segundo plano están activos: todos los subprocesos, excepto el GC, están en pausa, lo que significa que losfinally
bloques no se ejecutan.Edición obvia: se comportan igual aparte de la lógica que les permite manejar objetos IDisposable, d'oh.
Contenido adicional: se pueden apilar (donde los tipos difieren):
Y también delimitado por comas (donde los tipos son los mismos):
fuente
Su objeto MemoryStream se eliminará correctamente, no hay necesidad de preocuparse por eso.
fuente
Con la
using
declaración, el objeto se eliminará independientemente de la ruta de finalización.Otras lecturas...
fuente
Eche un vistazo a su código en reflector después de compilarlo. Verá que el compilador refactoriza el código para asegurarse de que se llame a dispose en la secuencia.
fuente