2008-09-29 20 views
40

¿El usuario detecta la excepción o la arroja? es decir,C# "Uso" de la sintaxis

using (StreamReader rdr = File.OpenText("file.txt")) 
{ 
//do stuff 
} 

Si el StreamReader se produce una excepción se captó mediante el uso o lanzado por lo que la función de llamada puede manejarlo?

Respuesta

28

usando sentencias no come excepciones.

Todo lo que "Utiliza" hace es enfocar su objeto al bloque de uso y llama automáticamente a Dispose() sobre el objeto cuando sale del bloque.

Sin embargo, si un hilo es abortado por una fuente externa, es posible que el Dispose nunca sea llamado.

+7

Estoy bastante seguro de que su "gotcha" no es precisa. Como la clase StreamReader implementa IDisposable, la sentencia using se ocupará de la eliminación del objeto. Debido a que la instrucción using actúa como un bloque finally, no importa si tiene una excepción o devolución. –

+12

De acuerdo con http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx, las instrucciones catch y finally se siguen ejecutando. Como "using" compila como un bloque finally, el lector de stread en su ejemplo será eliminado. – Uhall

+0

Estoy de acuerdo con los dos comentarios anteriores. Además del comentario de @ Uhall anterior, ThreadAbortException no aborta el hilo, solo atrapa la excepción que se genera como resultado. –

2

Si no se captura específicamente una excepción que ha arrojado hasta la pila hasta que algo hace

15

using permite la excepción a hervir a través. Actúa como un try/finally, donde finalmente elimina el objeto usado. Por lo tanto, solo es apropiado/útil para objetos que implementan IDisposable.

+0

+1. 'try/finally'. ¡Muchas gracias! – xagyg

2

El uso no interfiere con el manejo de excepciones además de limpiar cosas en su alcance.

No maneja las excepciones pero deja pasar las excepciones.

0

"using" no capta excepciones, solo dispone de recursos en caso de excepciones no controladas.

Quizás la pregunta es, ¿podría disponer de los recursos asignados entre paréntesis si también se produce un error en la declaración? Sin embargo, es difícil imaginar que ambos sucedan.

60

Cuando vea una declaración utilizando, pensar en este código:

StreadReader rdr = null; 
try 
{ 
    rdr = File.OpenText("file.txt"); 
    //do stuff 
} 
finally 
{ 
    if (rdr != null) 
     rdr.Dispose(); 
} 

Así que la verdadera respuesta es que no hace nada con la excepción lanzada en el cuerpo del bloque de usar. No lo maneja ni lo vuelve a lanzar.

5

Lanza la excepción, por lo que su método contenedor debe manejarlo o pasarlo a la pila.

try 
{ 
    using (
     StreamReader rdr = File.OpenText("file.txt")) 
    { //do stuff 
    } 
} 
catch (FileNotFoundException Ex) 
{ 
    // The file didn't exist 
} 
catch (AccessViolationException Ex) 
{ 
    // You don't have the permission to open this 
} 
catch (Exception Ex) 
{ 
    // Something happened! 
} 
2

using garantías * el objeto creado serán dispuestos en el extremo del bloque, incluso si se produce una excepción. La excepción es no atrapado. Sin embargo, debe tener cuidado con lo que hace si trata de atraparlo usted mismo. Como cualquier código que capte la excepción se encuentra fuera del bloque de alcance definido por la declaración using, su objeto no estará disponible para ese código.

* restricción de los sospechosos habituales, como falta de energía eléctrica, holocausto nuclear, etc

1

Usted puede imaginar usando como tratar ... finalmente bloque sin el bloque catch. En el bloque finally, se llama a IDisposable.Dispose, y como no hay ningún bloque catch, se generan excepciones en la pila.

3

Cualquier excepción que se genere en la expresión de inicialización de la instrucción using propagará el alcance del método y la pila de llamadas como se espera.

Sin embargo, una cosa a tener en cuenta es que si se produce una excepción en la expresión de inicialización, no se invocará el método Dispose() en la variable de expresión. Este es casi siempre el comportamiento que desea, ya que no desea molestarse en deshacerse de un objeto que en realidad no se creó. Sin embargo, podría haber un problema en circunstancias complejas. Es decir, si las inicializaciones múltiples están ocultas dentro del constructor y algunas tienen éxito antes de que se genere la excepción, entonces la llamada Dispose no puede ocurrir en ese punto. Sin embargo, esto no suele ser un problema, ya que los constructores generalmente se mantienen simples.

+0

Este es * siempre * el comportamiento que desea. Si se ocultan varias inicializaciones dentro del constructor, le corresponde al constructor administrar cualquier limpieza necesaria. Ningún código externo podría hacerlo, ya que el objeto no se creará en realidad. – Joe

+2

@Joe - Estoy tratando de sonar inteligente aquí. ¡Deja de señalar los defectos de mi lógica! –

3

En su ejemplo, si se lanza File.OpenText, se llamará Disposeno.

Si ocurre la excepción en //do stuff, llame al Dispose.

En ambos casos, la excepción normalmente se propaga fuera del alcance, como lo sería sin el utilizando la instrucción.