c# - practices - Intenta... ¿Bloques de captura siempre caros?
declare exception c# (10)
En general , en las implementaciones de hoy, ingresar un bloque try
no es caro 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, las excepciones normalmente deben usarse para eventos excepcionales , no para el control de flujo normal.
Sin embargo, el desempeño es solo un factor a considerar, especialmente en el mundo moderno. Si (por ejemplo) está haciendo algo una vez en respuesta a una acción del usuario, probablemente no importa desde el punto de vista del rendimiento si utiliza una excepción, incluso cuando podría haber realizado una verificación proactiva, siempre que la excepción sea lo suficientemente rápida el usuario no está sorprendido. 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 gran carga, probablemente desea evitar el uso de una excepción para un caso normal.
¹ Hace más de una década, fui responsable de las mejoras a una aplicación de .Net "sin implementación táctil" en la que la primera excepción lanzada tomó tres segundos. Este fue un problema suficiente en un caso de uso relacionado con la apertura de un archivo que el usuario había pedido y que, razonablemente, no estaría allí. Tenía que agregar una verificación de la existencia del archivo antes de intentar abrir el archivo, lo que normalmente es una mala práctica de programación (solo intente abrir el archivo y maneje la excepción si eso falla), simplemente porque la experiencia del usuario esperando que se construyera esa excepción fue muy mala. Pero probablemente ese no sea el mundo en el que vivimos ahora.
Posible duplicado:
¿Los bloques try / catch dañan el rendimiento cuando no se lanzan excepciones?
Hola a todos, solo una pregunta rápida sobre try..catch blocks. He escuchado 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 muchas excepciones para ser capturado a menos que sea un intento de eludir la validación. Mi pregunta es: ¿Los bloques de captura de Try ... solo son caros si se detecta una excepción o siempre es costoso independientemente de si se lanza una excepción?
Gracias
EDIT : Gracias por todas las respuestas. Decidí que dado que la comprobación (en C #) no es muy costosa, seguiré con este método. Esto se debe principalmente a que es raro que se produzca una excepción real, ya que existen pasos de validación anteriores que garantizan que nadie ingrese una dirección de correo electrónico no válida.
En general, los compiladores modernos imponen solo un costo mínimo en los bloques de try
menos que se lance una excepción. Aún 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 sentencia COME FROM
.
Esto depende del idioma, pero por lo que sé en Java, si no se lanza una excepción, casi no hay costo de rendimiento para tener un try
/ catch
.
Entonces, en su ejemplo de uso de direcciones de correo electrónico previamente validadas, lo que tiene está bien.
La sobrecarga del bloque try es muy baja, por lo que si no se lanza una excepción, no debería haber una penalización notable. La sobrecarga principal que se produce cuando se lanza una excepción es la caminata de pila que se realiza 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 sería que pudieras validar tus entradas correctamente de antemano, pero la validación del correo electrónico es bastante complicada, por lo que puede que no valga la pena en este caso.
Las excepciones solo son caras si se lanza una excepción. Estoy seguro de que hay un costo mínimo para configurar un bloque Try..Catch, pero el costo de no obtener la excepción y el bloqueo del programa supera con creces el costo. Como han señalado otros, los bloques Try..Catch solo deben usarse en circunstancias excepcionales.
Si bien es cierto que nunca debe usar try..catch para controlar el flujo del programa, no tengo conocimiento de ningún problema de rendimiento SI no se incluyen excepciones en el código
Solo es caro si se lanza la excepción, pero eso no es una excusa para usar las excepciones como control de flujo normal.
Si puede validar previamente algo para evitar que ocurra una excepción en primer lugar, entonces hágalo. Por ejemplo, en lugar de lo que publicaste, algo como esto sería preferible:
string invalidAddress = "notvalid@@@@@@lolzors.bomb";
return MailAddressValidator.IsValid(invalidAddress ); // doesn''t cause exception
La excepción a la regla es cuando tendría que rodar su propia versión de un método complicado (por ejemplo, algo que se encuentra en la biblioteca de clases 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, perfil utilizando datos representativos. Si se trata de un usuario que ingresa datos en un formulario de aplicación cliente cada dos segundos, no importará. Sin embargo, si se trata de un servicio para procesar lotes de miles de direcciones de correo electrónico que pueden provenir de cualquier lugar, debe estar seguro de sus suposiciones.
Solo para jugar a los demonios defensores: 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 demorar entre 10 y 120 minutos, lo cual está haciendo un montón de cosas diferentes, he encontrado que hacer (si ha cancelado) lanzar una nueva JobCancelledException () dentro de mi función Log () (que registra en cada paso en el que estoy) para trabajar simplemente friggan impresionante. Se rescata de la ejecución actual del código y deja de ejecutar el trabajo, exactamente lo que necesito. Estoy seguro de que hay una mejor manera de hacerlo, tal vez de alguna manera usando eventos, pero en mi caso funciona muy bien (especialmente porque los trabajos no se cancelan regularmente).
Aparte de eso, sin embargo, estoy totalmente de acuerdo en que las Excepciones nunca deben usarse como una herramienta de control de flujo.
@Kornel - Tengo dos palabras para esa publicación ... Holy $ hit =)
Aquí hay un ejemplo simple de pseudo código:
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
}
}
Son bastante baratos a menos que haya una excepción. Por lo tanto, debe evitarlos cuando se espera una excepción, como en el ejemplo anterior.
Creo que las excepciones en las malas entradas de los usuarios son generalmente imprudentes. Las excepciones en memoria insuficiente u otras fallas inesperadas están bien.
try..catch
bloques try..catch
nunca deben usarse como una herramienta para el control del flujo del programa.
Lee este hilo si no estás convencido.