c# - remarks - ¿Qué sucede si regreso antes de que termine el uso de la declaración? ¿Se llamará a los descartados?
summary c# documentation (5)
Con la instrucción using
, el objeto se eliminará independientemente de la ruta de finalización.
Otras lecturas...
Tengo el siguiente código
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
El método dispose()
se llama al final de using
llaves de declaración }
¿verdad? Dado que return
antes del final de la instrucción de using
, ¿se eliminará correctamente el objeto MemoryStream
? ¿Qué pasa aquí?
Eche un vistazo a su código en el reflector después de compilarlo. Descubrirá que el compilador refactoriza el código para asegurarse de que se invoque el desecho en la transmisión.
Sí, se llamará a Dispose
. Se invoca tan pronto como la ejecución abandona el alcance del bloque de using
, independientemente de los medios necesarios para abandonar el bloque, ya sea al final de la ejecución del bloque, una declaración de return
o una excepción.
Como @Noldorin señala correctamente, el uso de un bloque de using
en el código se compila en try
/ finally
, con Dispose
se llama en el bloque finally
. Por ejemplo, el siguiente código:
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
efectivamente se convierte en:
MemoryStream ms = new MemoryStream();
try
{
// code
return 0;
}
finally
{
ms.Dispose();
}
Entonces, como finally
se garantiza que se ejecutará después de que el bloque try
haya finalizado la ejecución, independientemente de su ruta de ejecución, se garantiza que se Dispose
, sin importar qué.
Para obtener más información, consulte este artículo de MSDN .
Apéndice:
Solo una pequeña advertencia para agregar: dado que se garantiza que se llamará a Dispose
, casi siempre es una buena idea asegurarse de que Dispose
nunca arroje una excepción cuando implemente IDisposable
. Desafortunadamente, hay algunas clases en la biblioteca central que arrojan en ciertas circunstancias cuando se llama Dispose
- ¡Te estoy mirando, WCF Service Reference / Client Proxy! - y cuando eso sucede, puede ser muy difícil rastrear la excepción original si se llamó a Dispose
durante un desenrollamiento de la pila de excepciones, ya que la excepción original se traga a favor de la nueva excepción generada por la llamada Dispose
. Puede ser enloquecedoramente frustrante. ¿O eso es frustrantemente enloquecedor? Uno de los dos. Tal vez ambos.
Su objeto MemoryStream se eliminará correctamente, no debe preocuparse por eso.
using
statements se comporta exactamente como try ... finally
blocks, por lo que siempre se ejecutará en cualquier ruta de salida de código. Sin embargo, creo que están sujetos a las pocas y raras situaciones en las que finally
no se convocan bloques. Un ejemplo que puedo recordar es si el hilo de primer plano sale mientras los hilos de fondo están activos: todos los hilos aparte del GC están en pausa, lo que significa que finally
bloques no se ejecutarán.
Edición obvia: se comportan de la misma manera que la lógica que les permite manejar objetos IDisposables, d''oh.
Contenido de bonificación: se pueden apilar (donde los tipos difieren):
using (SqlConnection conn = new SqlConnection("string"))
using (SqlCommand comm = new SqlCommand("", conn))
{
}
Y también delimitado por comas (donde los tipos son los mismos):
using (SqlCommand comm = new SqlCommand("", conn),
SqlCommand comm2 = new SqlCommand("", conn))
{
}