2009-03-19 19 views
17

Pregunta simple sobre mejores prácticas.C# anidado ¿Pruebe las declaraciones o los métodos de captura?

En caso de anidar, intente declaraciones catch o simplemente utilice métodos.

Por ejemplo, si tiene un método que abre un archivo que funciona y cierra el archivo, usted tendría el abrir y cerrar fuera del try catch, o más bien el cierre en el bloque finally.

Ahora, si su método abierto falla, el método sería correcto? Entonces, ¿deberías envolverlo en un bloque try catch o debería llamarse desde otro método, que a su vez es un bloque try catch?

+0

Código de ejemplo ayudará a ilustrar su pregunta. – Alan

+0

cualquier código de muestra (mejor real) para ilustrar la pregunta? – Kiquenet

Respuesta

4

Depende de lo que está intentando hacer, pero en la mayoría de los casos, try/catch anidados son un signo de una función demasiado compleja (o de un programador que no sabe cómo funcionan las excepciones).

En el caso del archivo abierto, usaría un titular IDisposable y una cláusula de uso, y así omitiría la necesidad de cualquier try/catch explícito.

7

Esta es una pregunta de estilo, pero para mí intento nunca tener más de un nivel de try/catch/finally nesting en un único método. En el momento en que golpea una prueba anidada, es casi seguro que ha violado el principio de funcionamiento 1 función = 1 y debe usar un segundo método.

+3

Creo que en muchos, si no en la mayoría de los desarrolladores, no será una cuestión de estilo. Será una cuestión de no entender las excepciones en .NET, y pensar que necesitan atrapar todas las excepciones, como en Java. En la mayoría de los casos, lo mejor es dejar que la excepción se propague. –

15

En el contexto de un método que abre un archivo, utilizaría una instrucción de uso frente a una captura de prueba. La instrucción using garantiza que se llama a Dispose si se produce una excepción.

using (FileStream fs = new FileStream(file, FileMode.Open)) 
{ 
    //do stuff 
} 

hace lo mismo que:

FileStream fs; 
try 
{ 
    fs = new FileStream(file, FileMode.Open); 
    //do Stuff 
} 
finally 
{ 
     if(fs!=null) 
      fs.Dispose(); 
} 
+3

Cerrar, pero el código try/finally no coincide exactamente con el código de uso. También debe envolverlo en un bloque de alcance anónimo. –

1

La mayoría de las veces me gustaría romper los bloques try/catch anidados en funciones. Pero a veces escribo código para capturar y registrar todas las excepciones no detectadas lanzadas por mi aplicación. Pero, ¿qué sucede si el código de registro falla? Por lo tanto, tengo otra oportunidad de intentarlo para evitar que el usuario vea el cuadro de diálogo predeterminado de excepción no controlada de .NET. Pero incluso este código podría ser fácilmente refactorizado en funciones en lugar de bloques try/catch anidados.

try 
{ 
    try 
    { 
     DoEverything(); 
    } 
    catch (Exception ex) 
    { 
     // Log the exception here 
    } 
} 
catch (Exception ex) 
{ 
    // Wow, even the log is broken ... 
} 
+1

¡Si su registro no funciona, debe permitir que la excepción se propague para que el usuario pueda quejarse de que su registro está interrumpido! –

+0

Aún puedo mostrar la excepción arrojada por el código de registro. Es solo que * I * quiero hacerlo en lugar de dejar que surja la ventana de error de marco. –

+0

cualquier buen patrón de muestra con la acción ? – Kiquenet

11

ahora que tenemos lambdas y la inferencia de tipos y algunas otras cosas, hay un lenguaje que es común en otros idiomas que ahora tiene mucho sentido en C#. Su ejemplo fue sobre abrir un archivo, hacerle algo y luego cerrarlo. Bien, ahora puede hacer un método de ayuda que abre un archivo, y también se asegura de cerrar/eliminar/limpiar, pero llama a una lambda que proporcione para la parte de "hacer cosas". Esto te ayudará a obtener las cosas complicadas de try/catch/finally dispose/cleanup en un solo lugar, y luego usarlas una y otra vez.

He aquí un ejemplo:

public static void ProcessFile(string filePath, Action<File> fileProcessor) 
{ 
    File openFile = null; 

    try 
    { 
    openFile = File.Open(filePath); // I'm making this up ... point is you are acquiring a resource that needs to be cleaned up after. 

    fileProcessor(openFile); 
    } 
    finally 
    { 
    openFile.Close(); // Or dispose, or whatever. 
    } 
} 

Ahora, las personas que llaman de este método no tiene que preocuparse acerca de cómo abrir el archivo o cerrar/disponer de él. Pueden hacer algo como esto:

Helpers.ProcessFile("C://somefile.txt", f => 
{ 
    while(var text = f.ReadLine()) 
    { 
    Console.WriteLine(text); 
    } 
}); 
+0

¿Puedo poner código "while" en un método de otra clase? – Kiquenet

+0

@alhambraeidos, si te estoy entendiendo correctamente, sí, puedes absolutamente. Puede hacer un método llamado "ForEachLine", que abre el archivo, hace un ciclo while para leerlo línea por línea, y llama a la función que pasa en cada línea. –

+0

Me gusta esto: MyHelperClass4Files.ForEachLine (f); ?? – Kiquenet

3

¿Qué tal si tiene un código relacionado que no pertenece necesariamente a una función independiente? ¿Esto entonces sería correcto?

try 
{ 
    // Part 1 Code Here 

    try 
    { 
    // Part 2 Code Here 
    } 
    catch (Exception ex) 
    { 
    // Error from Part 2 
    } 
} 
catch (Exception ex) 
{ 
    // Error from Part 1 
} 
-2
try 
{ 
    ---- 
} 
catch 
{ 
    try 
     { 
      --- 
     } 
    catch 
     { 
     --- 
     } 
} 
+0

¿Por qué se da este voto negativo? –

0
//create a switch here and set it to 0 
try 
{ 
    DoChunk1(); 
    //looks good. set the switch to 1 
} 
catch (Exception ex) 
{ 
    // Log the exception here 
} 

// comprobar el interruptor, si todavía cero es en este punto, entonces puede detener su programa aquí; de lo contrario, vuelva a poner el interruptor en cero y ejecute su siguiente declaración de captura de prueba. totalmente de acuerdo con dividirlos como se menciona arriba

try { DoChunk2(); // se ve bien. ajuste el interruptor en 1 } catch (Exception ex) { // Registrar la excepción aquí }

Cuestiones relacionadas