English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Manejo de excepciones de C#

Aquí, aprenderá a manejar excepciones en C# utilizando bloques try, catch y finally.

Es necesario manejar las excepciones en la aplicación para evitar que el programa se caiga y obtener resultados inesperados, registrar las excepciones y continuar ejecutando otras funciones. C# proporciona soporte integrado para manejar excepciones utilizando bloques try, catch y finally.

Sintaxis:

try
{
    // Colocar el código aquí puede generar una excepción
}
catch
{
    // Aquí se manejan las excepciones
}
finally
{
    // Código de limpieza final
}

bloque try:Cualquier código sospechoso que pueda generar una excepción debe colocarse en un bloque try{ }. Si se produce una excepción durante la ejecución, el flujo de control saltará al primer bloque catch que coincida.

catch bloque:El bloque catch es un bloque de manejo de excepciones donde puede ejecutar algunas operaciones, como registrar y auditar excepciones. El bloque catch toma un parámetro de tipo de excepción, que puede usar para obtener detalles de la excepción.

finally bloque:finally se ejecutará siempre, independientemente de si se lanza una excepción o no. generalmente, finally debe utilizarse para liberar recursos, como cerrar cualquier flujo o objeto de archivo abierto en el bloque try.

Si ingresa caracteres no numéricos, lo siguiente puede generar una excepción.

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Ingrese un número: ");
        var num = int.Parse(Console.ReadLine());
        Console.WriteLine($"Cuadrado de {num} es {num"); * num");
    }
}

Para manejar posibles excepciones en el ejemplo anterior, encierre el código en un bloque try y luego maneje la excepción en el bloque catch, como se muestra a continuación.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Ingrese un número: ");
            var num = int.parse(Console.ReadLine());
            Console.WriteLine($"Cuadrado de {num} es {num"); * num");
        }
        catch
        {
            Console.Write("Error occurred.");
        }
        finally
        {
            Console.Write("Re");-intente con un número diferente.");
        }
    }
}

En el ejemplo anterior, encerramos este código en un bloque try. Si se produce una excepción dentro del bloque try, el programa saltará al bloque catch. Dentro del bloque catch, mostraremos un mensaje para informar al usuario sobre su error, y en el bloque finally, mostraremos un mensaje sobre las operaciones posteriores al ejecutar el programa.

El bloque try debe estar seguido de catch o finally o ambos bloques. Si el bloque try no utiliza catch o el bloque finally, se producirá un error en tiempo de compilación.

En el caso ideal, el bloque catch debe contener parámetros de clases de excepciones integradas o personalizadas para obtener detalles de errores. A continuación, se incluye el tipo de parámetro Exception que captura todos los tipos de excepciones.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Ingrese un número: ");
            var num = int.parse(Console.ReadLine());
            Console.WriteLine($"Cuadrado de {num} es {num"); * num");
        }
        catch(Exception ex)
        {
            Console.Write("Error info:"); + ex.Message);
        }
        finally
        {
            Console.Write("Re");-intente con un número diferente.");
        }
    }
}

Filtros de excepciones

Puede usar múltiples bloques catch con diferentes tipos de parámetros de excepción. Esto se llama filtro de excepciones. Los filtros de excepciones son útiles cuando desea manejar diferentes tipos de excepciones de manera diferente.

class Program
{
    static void Main(string[] args)
    {
        Console.Write("Por favor, introduzca un número para dividir 100: ");
        
        try
        {
            int num = int.Parse(Console.ReadLine());
            int result = 100 / num;
            Console.WriteLine("100 / {0} = {1}
        }
        catch(DivideByZeroException ex)
        {
            Console.Write("No se puede dividir por cero. Por favor, inténtelo de nuevo.");
        }
        catch(InvalidOperationException ex)
        {
            Console.Write("Operación inválida. Por favor, inténtelo de nuevo.");
        }
        catch(FormatException ex)
        {
            Console.Write("No es un formato válido. Por favor, inténtelo de nuevo.");
        }
        catch(Exception ex)
        {
            Console.Write("Se produjo un error! Por favor, inténtelo de nuevo.");
        }
    }
}

En el ejemplo anterior, especificamos múltiples bloques catch con diferentes tipos de excepciones. Podemos mostrar mensajes adecuados al usuario según el error, por lo que el usuario no repetirá el mismo error.

Nota:
No se permite tener múltiples bloques catch con el mismo tipo de excepción. El bloque catch con el tipo de excepción base debe ser el último bloque.

Bloque catch inválido

No se permite usar un bloque catch sin parámetros y un bloque catch con parámetros Exception en la misma declaración try..catch, ya que ambos ejecutan la misma operación.

try
{
    //código que puede lanzar una excepción
}
catch //No se puede tener tanto catch y catch(Exception 异常)
{ 
    Console.WriteLine("Se produjo una excepción");
}
catch(Exception ex) //No se puede tener tanto catch y catch(异常异常)
{
    Console.WriteLine("Se produjo una excepción");
}

Además, el bloque catch sin parámetros catch {} o el bloque catch genérico catch (Exception ex){} deben ser el último bloque. Si hay otros bloques catch después de catch {} o catch (Exception ex), el compilador generará un error.

    Ejemplo: captura catch no válida

try
{
    //código que puede lanzar una excepción
}
catch
{ 
    // Este bloque de captura debe ser el último bloque
}
catch (NullReferenceException nullEx)
{
    Console.WriteLine(nullEx.Message);
}
catch (InvalidCastException inEx)
{
    Console.WriteLine(inEx.Message);
}

bloque finally

El bloque finally es un bloque opcional que debe estar después del bloque try o catch. Se ejecutará siempre el bloque finally, independientemente de si se produce una excepción o no. El bloque finally se utiliza generalmente para código de limpieza, como manejar objetos no administrados.

    Ejemplo: bloque finally

static void Main(string[] args)
{
    FileInfo file = null;
    try
    {
        Console.Write("Ingrese un nombre de archivo para escribir: ");
        string fileName = Console.ReadLine();
        file = new FileInfo(fileName);
        file.AppendText("¡Hola Mundo!")
    }
    catch(Exception ex)
    {
        Console.WriteLine("Ocurrió un error: {0}", ex.Message);
    }
    finally
    {
        // Aquí se limpiará el objeto archivo;
        file = null;
    }
}
finally no permite múltiples bloques. Además, el bloque finally no puede contener las palabras clave return, continue o break. No permite que la propiedad de control salga del bloque finally.

try anidado-catch

C# permite try anidado-catch en el bloque. Cuando se utiliza try anidado-catch en el bloque, la excepción se capturará en el primer bloque coincidente después del bloque try donde se produjo la excepción catch.

static void Main(string[] args)
{
    var divider = 0;
    try
    {
        try
        {
            var result = 100/divider;
        }
        catch
        {
            Console.WriteLine("Bucle catch interno");
        }
    }
    catch
    {
        Console.WriteLine("Bucle catch externo");
    }
}
Salida:
catch interno

catch en el ejemplo anterior, se ejecutará un bloque interno porque es el primer bloque que maneja todas las excepciones.

Si no hay un bloque catch interno que coincida con el tipo de excepción lanzada, el control fluirá hacia el bloque catch externo hasta encontrar el filtro de excepción adecuado. Vea el siguiente ejemplo.

static void Main(string[] args)
{
    var divider = 0;
    try
    {
        try
        {
            var result = 100/divider;
        }
        catch(NullReferenceException ex)
        {
            Console.WriteLine("Bucle catch interno");
        }
    }
    catch
    {
        Console.WriteLine("Bucle catch externo");
    }
}
Salida:
Bucle catch externo

En el ejemplo anterior, se generará una excepción de tipo DivideByZeroException. Debido a que el bloque catch interno solo maneja NullReferenceTypeException, el bloque catch externo lo manejará.