2010-01-15 12 views
21

Duplicar posibles:
Do try/catch blocks hurt performance when exceptions are not thrown?Prueba ... ¿Los bloques de captura siempre son caros?

Hola a todos, Sólo una pregunta rápida sobre try..catch bloques. He oído que son caros de usar y no deben usarse como parte del flujo de un programa. Sin embargo, para validar las direcciones de correo electrónico, estoy usando el siguiente código.

 try 
     { 
      MailAddress checkEmail = new MailAddress(testEmail); 

      return true; 
     } 
     catch 
     { 
      return false; 
     } 

Debido a la validación previa, no tengo que capturar muchas excepciones a menos que sea un intento de eludir la validación. Mi pregunta es, ¿lo intentan? Los bloques de captura solo son caros si se detecta una excepción, o ¿es siempre caro independientemente de si se produce alguna excepción?

Gracias

EDIT: Gracias por todas las respuestas. He decidido que, dado que la verificación (en C#) no es muy costosa, me quedaré con este método. Se debe principalmente a que se produce una excepción real, ya que existen pasos de validación previos que aseguran que nadie ingrese accidentalmente una dirección de correo electrónico no válida.

+1

Una gran pregunta. – stone

+12

Usted dice que la excepción nunca debe ocurrir, y si lo hace, es el resultado de alguien que intenta eludir sus mecanismos de seguridad. ¿Parece sabio comer la excepción y seguir alegremente, ahora que sabes que hay un atacante suelto en el sistema? Dejaría que la excepción saltara a la persona que llama y * detenga el programa *. Cuando notes que hay un tipo hostil con un hacha que ha pasado por alto la seguridad de tu edificio y él activa una alarma, * suena la alarma * y convoca la seguridad; ¡no apagas la alarma automáticamente! –

+3

Hola Eric. Mi código real es significativamente más grande que esto. Monitorea al usuario, registra datos y bloquea el acceso. Simplemente mostré una llamada de ejemplo que estaba haciendo para ver si era o no una manera eficiente de hacer las cosas :) – Skoder

Respuesta

19

En general, , en la actualidad de implementaciones, ingresar un bloque try no es costoso en absoluto (esto no siempre fue cierto). Sin embargo, lanzar y manejar una excepción suele ser una operación relativamente costosa. Por lo tanto, normalmente se deben usar excepciones para eventos excepcionales, no control de flujo normal.

Sin embargo, el rendimiento es solo un factor a tener en cuenta, especialmente en el mundo moderno.Si (por ejemplo) está haciendo algo una vez en respuesta a una acción del usuario, probablemente no importe desde el punto de vista del rendimiento si usa una excepción incluso cuando podría haber hecho un chequeo proactivo, siempre que la excepción ocurra lo suficientemente rápido el usuario no se sobresalta. Pero si está haciendo algo en un circuito cerrado que se ejecutará cientos de miles de veces, o si está escribiendo una aplicación web que puede necesitar manejar una carga enorme, probablemente quiero evitar usar una excepción para un caso normal.


¹ Hace más de una década que era responsable de mejoras a un .Net 1.1 "ningún despliegue toque" aplicación en la que la primera excepción que se tienen plenamente tres segundos. Esto era un problema suficiente en un caso de uso que involucraba abrir un archivo que el usuario había pedido y que razonablemente podría no estar allí, tuve que agregar un cheque para la existencia del archivo antes de tratar de abrirlo, lo que normalmente es una mala práctica de programación (solo intente abrir el archivo y manejar la excepción si eso falla), simplemente porque la experiencia del usuario que esperaba que se construyera esa excepción era tan pobre. Pero probablemente ese no sea el mundo en el que vivimos ahora.

+0

Hola, lo siento, pensé que había etiquetado C#. Lo he arreglado ahora. Solo espero lanzar la excepción si un usuario ha manipulado deliberadamente el encabezado POST ya que la validación estándar se aplica en la entrada. – Skoder

+2

Muy bien puesto respuesta @ T.J. También agregaría con respecto al rendimiento alcanzado al manejar una excepción, no olvide que en ese momento la aplicación ha dejado de comportarse como se esperaba (es decir, los proverbiales han afectado al fan), lo que indica un problema mayor que debe ser resuelto , por lo tanto, el rendimiento probablemente no sea una gran preocupación en ese momento. Por supuesto, esto sigue al punto de T.J. de "las excepciones solo deben usarse para eventos excepcionales", algo que todavía encuentro que muchos desarrolladores no aprecian. –

+0

¿Desde cuándo está abriendo un archivo una operación de rendimiento crítico? El try-catch de la IMHO es más legible en este caso y la diferencia de rendimiento es insignificante en comparación con la complejidad general de la operación. – dsimcha

1

try..catch bloques nunca se deben utilizar como una herramienta para el control de flujo del programa.

Lea this thread si no está convencido.

+1

¿Nunca? ¿Nunca jamás? Incluso si entiendes profundamente lo que está pasando? Y si, como en el caso actual, es una manera fácil, efectiva y sin errores de hacer algo que de otro modo sería difícil de hacer. (-1 por ningún esfuerzo para distinguir el caso actual del principio general). –

+0

@ Boris, especialmente si se ejecuta en un bucle de 1 millón de iteraciones. –

2

Son bastante baratos a menos que exista una excepción. Por lo tanto, debe evitarlos cuando se espera una excepción, como en su ejemplo anterior.

Creo que las excepciones a la mala entrada de los usuarios son generalmente imprudentes. Las excepciones de falta de memoria u otras fallas inesperadas están bien.

+0

La entrada se valida normalmente utilizando expresiones regulares. Sin embargo, si alguien ha eludido deliberadamente la validación (alterando el encabezado POST), esta excepción se lanzará potencialmente. – Skoder

+0

Es una llamada de juicio. Pero diría que eso es lo suficientemente excepcional. –

0

En general, los compiladores modernos imponen solo un costo mínimo en los bloques try a menos que se produzca una excepción. Todavía no deben usarse para el control de flujo del programa, ya que no son tan obvios como las construcciones de flujo estándar. Una excepción es esencialmente equivalente a una declaración COME FROM.

1

Las excepciones son solo costosas si se lanza una excepción. Estoy seguro de que hay un costo muy bajo para configurar un bloque Try..Catch, pero está muy por encima del costo de no captar la excepción y tener el programa bloqueado. Como han señalado otros, los bloques Try..Catch deben usarse solo en circunstancias excepcionales.

0

Si bien es cierto que nunca se debe utilizar try..catch para el control de flujo del programa, no tengo conocimiento de ningún problema de rendimiento SI no hay excepciones son en realidad arrojados en el código

0

Esto depende del idioma, pero hasta donde yo sé en Java, si no se lanza una excepción, no hay costo de rendimiento para tener un try/catch.

Por lo tanto, en su ejemplo de uso de direcciones de correo electrónico validadas previamente, lo que tiene está bien.

+0

Gracias. Estoy usando C# (he corregido la etiqueta).Supongo que es algo similar en C# como en Java. Estoy usando una dirección de correo electrónico validada previamente para garantizar la integridad, pero esto siempre se llama independientemente. – Skoder

1

La sobrecarga del bloque try es muy baja, por lo que si no se produce una excepción, no debe haber una penalización notable. La sobrecarga principal que ocurre cuando se lanza una excepción es el recorrido de la pila que se lleva a cabo en busca de un controlador: ya que está almacenando en caché la excepción tan cerca de la fuente, dudo que haya mucho de un problema de rendimiento. Lo ideal es que sea capaz de validar sus entradas correctamente de antemano, pero la validación del correo electrónico es bastante complicada, por lo que puede no valer la pena en este caso.

2

Just to play Devils advocate: he encontrado un gran uso para usar excepciones para el control de flujo: el botón 'cancelar'.

Si tiene una función ejecutándose en algún servicio que puede tomar 10-120 minutos, lo que está haciendo un montón de cosas diferentes, he encontrado que hacer si (hasCanceled) arrojar nueva JobCancelledException() dentro de mi Log () función (que registra en cada paso en el que estoy) para trabajar simplemente increíble. Se libera de la ejecución actual de código y deja de ejecutar el trabajo, exactamente lo que necesito. Estoy seguro de que hay alguna forma mejor de hacerlo, tal vez de alguna manera el uso de eventos, pero para mi caso funciona muy bien (especialmente porque los trabajos no se cancelan regularmente).

Aparte de eso, sin embargo - Estoy 100% de acuerdo en que las excepciones no deben ser utilizados como una herramienta de control de flujo ..

@Kornel - Tengo dos palabras para ese puesto ... $ Santo hit =)

aquí es un simple ejemplo de código de pseudo:

Class Job 
{ 
     Public Run(param1,param2,etc...) 
     { 
      Try 
      { 
        Log("Doing Something") 
        DoSomething() 

         Log("Doing Another") 
         DoAnother() 

         Log("This keeps going, etc, inside of these function we make the same Log calls where it makes sense") 
         Etc() 
        } 
        Catch(JobCancelledException) 
        { 
         status="Cancelled" 
        } 
      } 

       Private Log(ByVal str As String) 
       { 
         MessateToUser(str) 

         if(hasCancelled) 
          throw new JobCancelledException 
      } 

      private SomeEvent_WhenUserPushesCancelButton() 
      { 
         hasCancelled=True 
      } 
} 
+0

¿No lo entiendo? –

+0

Es una forma de implementar el botón/funcionalidad 'cancelar' de algún trabajo que un usuario puede ejecutar. Este trabajo puede tardar horas en ejecutarse dados los parámetros correctos. I Log() en cada paso diferente de todos modos para dar feedback al usuario. Así que cada vez que inicio sesión, compruebo un campo hasCancelled y, si es cierto, arrojo una JobCancelledException. Ahora, sin importar dónde estemos en el código, el trabajo se detendrá inmediatamente, ya que manejo esta excepción en el nivel más alto de la pila de llamadas. Súper simple y funciona genial. – dferraro

1

es sólo es caro si se produce la excepción, pero eso no es una excusa para usar excepciones como el control de flujo normal.

Si puede validar previamente algo para evitar que ocurra una excepción en primer lugar, hágalo. P.ej. en lugar de lo que usted envió, algo como esto sería preferible:

string invalidAddress = "[email protected]@@@@@lolzors.bomb"; 
return MailAddressValidator.IsValid(invalidAddress); // doesn't cause exception 

La excepción a la regla es cuando usted tendría que rodar su propia versión de un método complicado (por ejemplo,algo que se encuentra en la biblioteca de la clase base que no tiene un método TryParse) solo para evitar una excepción que, en el gran esquema de cosas, simplemente no importa.

Si no está seguro, perfile usando datos representativos. Si es un usuario que ingresa datos en una aplicación de cliente cada dos segundos, no tendrá importancia. Sin embargo, si se trata de un servicio para procesar lotes de miles de direcciones de correo electrónico que pueden venir de cualquier lugar, debe estar seguro de sus suposiciones.

Cuestiones relacionadas