2011-12-31 8 views
17

tengo la pregunta: "? ¿Qué prefieres, manejo de excepciones o si la condición"si condición vs gestor de excepciones

para una entrevista. Mi respuesta fue que los manejadores de excepciones son preferidos solo por circunstancias excepcionales, como un error de permiso de disco en la escritura de archivos. El entrevistador parecía estar esperando otra respuesta. ¿Cuál es la respuesta correcta?

EDITAR: ¿Algún ejemplo particular donde el manejo de excepciones se usa comúnmente cuando una condición if hubiera sido más apropiada?

+5

'El entrevistador parecía estar esperando alguna otra respuesta' - entonces ¿por qué no le preguntas? Siempre estoy más impresionado por una pregunta que por una respuesta al entrevistar ... –

Respuesta

23

Como esta pregunta está etiquetada como "C#", podemos consultar las Pautas de diseño de .NET Framework como un buen punto de partida para responder este tipo de preguntas. Esta es la guía dada en MSDN bajo "Exception Throwing":

No use excepciones para un flujo de control normal, si es posible. Excepto para fallas del sistema y operaciones con posibles condiciones de carrera, los diseñadores del framework deben diseñar API para que los usuarios puedan escribir el código que no arroje excepciones. Por ejemplo, puede proporcionar una forma de verificar las condiciones previas al antes de llamar a un miembro para que los usuarios puedan escribir el código que no arroje excepciones.

Aquí se muestra un ejemplo de un mal práctica donde se manipula una excepción, pero casi siempre puede evitarse:

public int? GetItem(int index) 
{ 
    int? value = null; 
    try 
    { 
     value = this.array[index]; 
    } 
    catch (IndexOutOfRangeException) 
    { 
    } 

    return value; 
} 

Esto parece ideado pero veo código como este muy a menudo a partir de nuevos programadores. Suponiendo una sincronización adecuada alrededor de las lecturas y escrituras en array, esta excepción se puede evitar de manera determinista al 100%. Teniendo en cuenta que, una mejor manera de escribir ese código sería el siguiente:

public int? GetItem(int index) 
{ 
    int? value = null; 

    // Ensure the index is within range in the first place! 
    if (index >= 0 && index < this.array.Length) 
    { 
     value = this.array[index]; 
    } 

    return value; 
} 

Hay otros casos en los que no se puede evitar de una manera excepciones y sólo hay que manejarlos. Esto se presenta con mayor frecuencia cuando tiene que tratar con recursos externos, como archivos o conexiones de red, a los que podría perder acceso o contactar en cualquier momento. Ejemplo de WCF:

public void Close() 
{ 
    // Attempt to avoid exception by doing initial state check 
    if (this.channel.State == CommunicationState.Opened) 
    { 
     try 
     { 
      // Now we must do a (potentially) remote call; 
      // this could always throw. 
      this.channel.Close(); 
     } 
     catch (CommunicationException) 
     { 
     } 
     catch (TimeoutException) 
     { 
     } 
    } 

    // If Close failed, we might need to do final cleanup here. 
    if (this.channel.State == CommunicationState.Faulted) 
    { 
     // local cleanup -- never throws (aside from catastrophic situations) 
     this.channel.Abort(); 
    } 
} 

Incluso en el ejemplo anterior, es bueno comprobar que la operación que se va a hacer por lo menos tiene la oportunidad de éxito. Entonces todavía hay una verificación if(), seguida por la lógica de manejo de excepciones apropiada.

+0

En su ejemplo 'GetItem', la persona que llama no puede determinar si se proporcionó un 'índice' inválido, o si 'array [index]' contiene un valor 'null'. Entonces la pregunta sigue siendo qué es mejor. ¿Debería lanzar una excepción si se usó un índice no válido? ¿O simplemente devolverá un valor 'nulo' sin ninguna indicación de que se haya producido un error? El uso de un índice no válido en una matriz también causará una excepción, ¡no devolverá el valor predeterminado del tipo de matriz! – comecme

+2

@comecme: en ese ejemplo, puede suponer que 'array' se declaró como' int [] ', por lo que' null' solo puede significar que el valor no existe (out o rango). Sí, la persona que llama no lo sabrá, pero el implementador * sabrá y no deberá usar excepciones como flujo de control, que fue el punto del ejemplo. Es válido devolver un valor predeterminado sin lanzar una excepción, aunque generalmente se espera que este patrón se exprese en un método 'TryXxx', como se explica aquí: http://msdn.microsoft.com/en-us/library/ms229009.aspx – bobbymcr

10

El manejo de excepciones es una operación pesada y costosa en lo que respecta al rendimiento. Si puede evitar la captura de una excepción mediante el uso adecuado de if else que puede aumentar el rendimiento de la aplicación

Por otro lado, si el bloque tiene más sentido para el lector de código. Son fáciles de entender y mantener en comparación con el bloqueo de prueba excepcional. Ellos describen el flujo del programa de una manera más elegante

Y, finalmente, como usted ha dicho El manejo de excepciones debe ser para situaciones de incertidumbre o para casos excepcionales que no debería ser la opción por defecto

Editar

Un mal común práctica he visto en algunos lugares es este

try 
{ 
    string str = "Some String" 
    int i = Convert.ToInt32(str); 
} 
catch (Exception ex) 
{ 
     MessageBox.Show("Invalid input");   
} 

Ahora intenta captura se puede evitar fácilmente de esta carcasa mediante el uso de otra cosa si

string str = "Some String" 
    int i; 
    if(!int.TryParse(str, out i)) 
    { 
     MessageBox.Show("Invalid input");   
    } 
+1

Normalmente, la clase que convierte la cadena no sería la clase que muestra los mensajes de error. Es por eso que existen excepciones: pueden ser atrapados en un nivel superior. – comecme

4

La respuesta correcta es la que usted dio.

Para mayor especificidad, debería haber dicho algo en el sentido de "Yo uso declaraciones if siempre que sea posible debido a la sobrecarga de atrapar y arrojar excepciones".

0

Si conoce el inicio de sesión exacto del programa y conoce los errores que pueden ocurrir, puede escribir la instrucción if-else o, en otro caso, puede dejar las cosas para intentar detectar el manejo de excepciones.

2

Normalmente prefiero usar algún valor especial indefinido (por ejemplo, nulo para objetos) para indicar que algunos cálculos no pueden producir un resultado válido debido a una entrada no válida. Esto significa que mi código podría determinar e informar exitosamente que los datos de entrada no son válidos y que no se puede producir ningún resultado significativo.

Prefiero usar una excepción cuando mi código no puede completar el cálculo solicitado, p. si un archivo que contiene algunos datos requeridos no existe, si no se puede conectar a una base de datos.

Así conceptualmente:

  • resultado Indefinido (más si la condición): programa determina con éxito que no hay salida válida para la entrada dada.
  • Excepción (más try-catch): el programa no puede completar el cálculo debido a algún error en la aplicación no relacionada con la entrada.
Cuestiones relacionadas