Manejo de errores en C#: try/catch y más
El manejo de errores es uno de los componentes clave de un software confiable. En C#, se utiliza el mecanismo de excepciones (exceptions) para este propósito. La aplicación adecuada de las construcciones try, catch y finally no solo permite evitar la terminación abrupta del programa, sino que también hace que el código sea más legible y predecible. En este artículo, analizaremos los fundamentos del manejo de excepciones, las mejores prácticas y las capacidades avanzadas que ofrece la plataforma .NET.
1. Bloque básico try/catch/finally
La herramienta principal para el manejo de errores en C# es el bloque try-catch-finally. Su sintaxis es intuitiva:
- try — contiene el código que puede lanzar una excepción.
- catch — captura y maneja la excepción.
- finally — se ejecuta siempre, independientemente de si hubo una excepción. Se utiliza para liberar recursos (cerrar archivos, conexiones a la base de datos).
Veamos un ejemplo simple: división por cero:
using System;
class Program{ static void Main() { try { int a = 10; int b = 0; int result = a / b; // Aquí se generará una excepción Console.WriteLine($"Resultado: {result}"); } catch (DivideByZeroException ex) { Console.WriteLine($"Error: {ex.Message}"); } finally { Console.WriteLine("Bloque finally ejecutado."); } }}Salida del programa:
Error: Intento de dividir por cero.Bloque finally ejecutado.Tenga en cuenta: si no se especifica un tipo de excepción concreto, el bloque catch capturará todas las excepciones. Esto puede ser conveniente, pero a menudo se considera una mala práctica, ya que oculta problemas reales.
2. Tipos de excepciones y su jerarquía
En C#, todas las excepciones heredan de la clase base System.Exception. Las más utilizadas son:
SystemException— clase base para excepciones del sistema.NullReferenceException— acceso a un objeto que esnull.IndexOutOfRangeException— acceso fuera de los límites de un array.InvalidOperationException— llamada a un método en un estado no válido.ArgumentExceptiony sus derivados (ArgumentNullException,ArgumentOutOfRangeException) — argumentos de método incorrectos.
Puede capturar varios tipos de excepciones en un solo bloque catch (a partir de C# 6):
try{ // código}catch (ArgumentNullException ex) when (ex.ParamName == "userId"){ Console.WriteLine("El parámetro userId no debe ser null.");}catch (InvalidOperationException ex){ Console.WriteLine($"Operación no válida: {ex.Message}");}catch (Exception ex) when (Log(ex, "Error desconocido")){ // Filtro de excepciones: el bloque se ejecuta solo si la condición es verdadera throw; // Relanza la excepción}Los filtros de excepciones (palabra clave when) permiten un control más flexible de la lógica de manejo sin perder la pila de llamadas.
3. Generación de excepciones propias
A veces las excepciones estándar no son suficientes. Puede crear su propia clase de excepción heredando de Exception:
public class InvalidAgeException : Exception{ public int Age { get; }
public InvalidAgeException(int age, string message) : base(message) { Age = age; }
public InvalidAgeException(int age, string message, Exception inner) : base(message, inner) { Age = age; }}Ahora