CodeGym /Cursos /C# SELF /Múltiples catch y filtros en C#

Múltiples catch y filtros en C#

C# SELF
Nivel 13, Lección 4
Disponible

1. Introducción

Cuando tu programa se vuelve un poco más complejo que un simple Hello, world!, enseguida te topas con el reto de manejar errores de distintos tipos de formas diferentes. Imagina: trabajas con archivos, red, base de datos — y para cada escenario de error la reacción debe ser distinta. Por ejemplo, si falta un archivo puedes sugerir al usuario elegir otro, y si hay un error de red — repetir la operación o mostrar un mensaje animando tipo "Revisa el cable, a ver si el gato lo ha mordido otra vez".

En C# para esto se usan varios bloques catch seguidos. Cada bloque se especializa en su propio tipo de excepción (y sus herederos).

Estructura de múltiples catch


try
{
    // Aquí va el código que puede lanzar diferentes excepciones
}
catch (FileNotFoundException ex)
{
    Console.WriteLine($"Archivo no encontrado: {ex.Message}");
}
catch (IOException ex) // captura todos los errores de entrada/salida, excepto FileNotFoundException
{
    Console.WriteLine($"Error de entrada/salida: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"Algo salió mal: {ex.Message}");
}
Múltiples bloques catch para distintos tipos de errores

¡Importante! El compilador recorre los bloques de arriba abajo y elige el primero que encaje por tipo. Si se captura un FileNotFoundException, ya no sigue buscando más abajo.

Ilustración de la "cadena"

Tipo de excepción ¿Qué bloque la captura?
FileNotFoundException El primer catch
IOException (otro) El segundo catch
ArgumentException El tercero (general) catch

¿Por qué no mezclar?
La trampa más "amplia" — por ejemplo, con catch (Exception) — siempre ponla al final, si no, "tragará" todas las excepciones antes de tiempo y los catch especializados nunca se ejecutarán.

Es como apagar todas las alarmas de incendio del edificio solo porque una saltó por una tostadora quemada: así los siguientes incendios pasarán desapercibidos para el sistema.

Ejemplo práctico

using System;
using System.IO;

class Program
{
    static void Main()
    {
        try
        {
            double result = CalculateAverageAgeFromFile("users.txt");
            Console.WriteLine($"Edad media — {result}");
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine("Error: archivo no encontrado. Revisa la ruta.");
        }
        catch (FormatException ex)
        {
            Console.WriteLine("Error de datos: no se puede leer la edad.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Otro error: {ex.Message}");
        }
    }

    static double CalculateAverageAgeFromFile(string filePath)
    {
        // (Implementación: lee el archivo, parsea edades, calcula la media)
        // ...
        throw new NotImplementedException();
    }
}

Aquí separamos claramente qué hacer si falta el archivo (FileNotFoundException), y qué si los datos del archivo están "mal" (FormatException). Todos los demás casos los pilla el tercer bloque "de reserva".

2. Filtros catch: capturando matices

Los múltiples bloques catch son útiles, pero a veces no basta. Puede que dentro de un mismo tipo de excepción quieras reaccionar de forma distinta, según las circunstancias.

Por ejemplo, si la red no funciona porque se acabó el internet — podemos intentar reconectar. Pero si el servidor simplemente no responde — quizá hay que mostrar otro mensaje.

Aquí entran en juego los filtros catch — una supercaracterística de C# que te permite capturar no solo por tipo, sino también por una condición adicional.

Sintaxis del filtro when


catch (IOException ex) when (ex.Message.Contains("no hay disco"))
{
    Console.WriteLine("¡Ups! Parece que quitaste el pendrive.");
}
catch (IOException ex)
{
    Console.WriteLine("Otro error de entrada/salida: " + ex.Message);
}
Filtro catch when para afinar las condiciones de captura

Aquí el primer bloque solo captura aquellos IOException cuyo mensaje contiene la frase "no hay disco" — todo lo demás va al segundo bloque.

Aplicación en la vida real

Los filtros son especialmente útiles al trabajar con errores de red, cuando según las propiedades internas de la excepción decides si reintentar o simplemente informar del error.

Otro ejemplo: imagina que en un método que parsea un archivo, no quieres solo un FormatException "genérico", sino distinguir si el problema es con la edad (por ejemplo, si la edad está escrita como "abc" en vez de un número).

catch (FormatException ex) when (ex.Message.Contains("edad"))
{
    Console.WriteLine("Error: no se pudo leer la edad. Revisa los datos.");
}
catch (FormatException ex)
{
    Console.WriteLine("Error de formato de datos: " + ex.Message);
}

Filtros y rendimiento

Los filtros son muy cómodos, pero recuerda que la condición del filtro se evalúa antes de entrar al bloque catch, o sea, si no se cumple — el cuerpo del bloque ni se toca.

Por cierto, si el filtro lanza una excepción por sí mismo (por ejemplo, si en tu expresión en when ocurre una división por cero) — esa excepción catch nunca la capturará. Hay que tener cuidado con eso.

3. Combinando múltiples catch y filtros

Imagina que en tu proyecto necesitas manejar no solo el tipo de excepción, sino también su estado interno. Por ejemplo, al trabajar con IOException quieres comportamientos distintos si el error del sistema de archivos es por permisos o por falta de espacio en disco.


try
{
    File.AppendAllText("log.txt", "Nuevo registro\n");
}
catch (IOException ex) when (ex.Message.Contains("Sin espacio"))
{
    Console.WriteLine("Error: ¡No queda espacio en el disco!");
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("Error: no tienes permisos para escribir el archivo. Ejecuta como administrador.");
}
catch (IOException ex)
{
    Console.WriteLine("Otro error de disco: " + ex.Message);
}
Combinando filtros y diferentes tipos de catch

Aquí usamos tanto filtro como separación por tipos de error. Esta flexibilidad es especialmente valiosa al desarrollar una app compleja, donde es importante reaccionar de forma informativa ante fallos frecuentes.

4. Particularidades y "trampas" de los filtros y múltiples catch

  • El filtro catch puede usar la variable de excepción (ex), pero no puede modificarla.
  • Si lanzas una excepción dentro de when, no será "capturada" por ese mismo catch — subirá por la pila como si el filtro no existiera.
  • La lógica del filtro pasa a ser parte del contrato: tu compi de proyecto debe saber que no todo IOException será capturado — solo si se cumple la condición.
  • Si usas solo un catch para todo el método, pero dentro pones un filtro, puede que algunas excepciones "de más" no las captures nunca. Así que si tienes dudas — usa bloques explícitos y separados.
  • En apps grandes puedes usar filtros para lógica centralizada, por ejemplo, loguear solo errores críticos.

5. Escenarios para entrevistas y trabajo real

Saber de filtros y múltiples catch no es solo para lucirse o sacar nota en clean code. Es una habilidad real que te pueden pedir en entrevistas, sobre todo si el puesto implica mantener una app grande, compleja y distribuida.

Ejemplos de preguntas:

  • ¿Cómo manejarías en C# distintos escenarios de error al leer un archivo, para mostrar mensajes diferentes según la situación (archivo no existe, disco ocupado, datos corruptos)?
  • ¿Cómo evitar "tapar" un error importante si pones un bloque general catch (Exception)?
  • ¿Para qué sirve el filtro catch? ¿Puede haber un throw dentro?
2
Tarea
C# SELF, nivel 13, lección 4
Bloqueada
Manejo de excepciones usando múltiples `catch`
Manejo de excepciones usando múltiples `catch`
2
Tarea
C# SELF, nivel 13, lección 4
Bloqueada
Uso de filtros `catch`
Uso de filtros `catch`
1
Cuestionario/control
Introducción a las excepciones, nivel 13, lección 4
No disponible
Introducción a las excepciones
Stack de llamadas y creación de tus propias excepciones
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION