CSharp
Tutorial CSharp: Excepciones
Aprende a manejar excepciones en C# con try-catch, múltiples catch, finally y throw para crear programas robustos y controlados.
Aprende CSharp y certifícateTry-catch básico
El manejo de excepciones es una parte fundamental de la programación en C# que nos permite controlar los errores que pueden ocurrir durante la ejecución de nuestro programa. En lugar de permitir que un error detenga completamente la aplicación, podemos capturar estos errores y responder a ellos de manera controlada.
La estructura básica para manejar excepciones en C# es el bloque try-catch. Este mecanismo nos permite "intentar" ejecutar un bloque de código y "capturar" cualquier excepción que pueda ocurrir durante su ejecución.
Sintaxis básica
La estructura try-catch tiene la siguiente forma:
try
{
// Código que podría generar una excepción
}
catch (Exception ex)
{
// Código que se ejecuta si ocurre una excepción
}
Veamos un ejemplo sencillo para entender cómo funciona:
using System;
class Program
{
static void Main()
{
try
{
Console.Write("Introduce un número: ");
string input = Console.ReadLine();
int numero = int.Parse(input);
Console.WriteLine($"Has introducido el número: {numero}");
}
catch (Exception ex)
{
Console.WriteLine("Ha ocurrido un error: " + ex.Message);
}
Console.WriteLine("El programa continúa ejecutándose.");
}
}
En este ejemplo, si el usuario introduce algo que no sea un número (como una letra), el método int.Parse()
generará una excepción. En lugar de que el programa se detenga con un error, el bloque catch capturará la excepción y mostrará un mensaje amigable.
¿Qué es una excepción?
Una excepción es un objeto que contiene información sobre un error que ha ocurrido durante la ejecución del programa. Cuando se produce un error, C# crea un objeto de excepción y lo "lanza" (throw). Si este objeto no es capturado por un bloque catch, el programa terminará abruptamente.
Todas las excepciones en C# derivan de la clase base System.Exception
, que proporciona propiedades útiles como:
- Message: Descripción del error
- StackTrace: Secuencia de llamadas que llevaron al error
- InnerException: Excepción que causó la excepción actual (si existe)
Ejemplo práctico
Veamos un ejemplo más completo que muestra cómo el try-catch puede ayudarnos a manejar diferentes situaciones de error:
using System;
class Program
{
static void Main()
{
int[] numeros = { 10, 20, 30 };
try
{
// Intentamos acceder a una posición que no existe en el array
Console.WriteLine($"El cuarto elemento es: {numeros[3]}");
// Este código nunca se ejecutará si ocurre la excepción anterior
Console.WriteLine("Esta línea no se ejecutará si hay error");
}
catch (Exception ex)
{
Console.WriteLine($"Se produjo un error: {ex.Message}");
Console.WriteLine($"Tipo de excepción: {ex.GetType().Name}");
}
Console.WriteLine("El programa continúa después del error");
}
}
En este caso, intentamos acceder al cuarto elemento de un array que solo tiene tres elementos. Esto generará una excepción de tipo IndexOutOfRangeException
. El bloque catch capturará esta excepción y mostrará información sobre ella.
Flujo de ejecución
Es importante entender el flujo de ejecución cuando se trabaja con bloques try-catch:
- El código dentro del bloque try se ejecuta normalmente.
- Si no ocurre ninguna excepción, el bloque catch se ignora.
- Si ocurre una excepción en el bloque try, la ejecución de este bloque se detiene inmediatamente.
- El control se transfiere al bloque catch correspondiente.
- Después de ejecutar el bloque catch, el programa continúa con la siguiente instrucción después del bloque try-catch.
Veamos esto con un ejemplo:
using System;
class Program
{
static void Main()
{
Console.WriteLine("Inicio del programa");
try
{
Console.WriteLine("Inicio del bloque try");
int resultado = 10 / 0; // Esto generará una excepción
Console.WriteLine("Esta línea nunca se ejecutará");
}
catch (DivideByZeroException ex)
{
Console.WriteLine("Se capturó una excepción: " + ex.Message);
}
Console.WriteLine("Fin del programa");
}
}
La salida de este programa será:
Inicio del programa
Inicio del bloque try
Se capturó una excepción: Attempted to divide by zero.
Fin del programa
Observa que la línea "Esta línea nunca se ejecutará" no aparece en la salida porque la ejecución del bloque try se interrumpe cuando ocurre la excepción.
Cuándo usar try-catch
Es importante usar los bloques try-catch de manera adecuada. Algunas situaciones donde son especialmente útiles:
- Operaciones de entrada/salida: Lectura/escritura de archivos, conexiones de red.
- Conversión de tipos: Cuando se convierte un string a un tipo numérico.
- Acceso a elementos de colecciones: Cuando se accede a índices que podrían no existir.
- Operaciones matemáticas: División por cero, desbordamientos.
Sin embargo, no es recomendable usar try-catch para controlar el flujo normal del programa. Por ejemplo:
// Mal uso de try-catch (no recomendado)
try
{
if (usuario.EsAdmin)
{
// Código para administradores
}
else
{
throw new Exception("No eres administrador");
}
}
catch (Exception)
{
// Código para usuarios normales
}
En este caso, sería mejor usar una simple estructura if-else sin excepciones.
Ejemplo de aplicación real
Veamos un ejemplo más práctico donde el manejo de excepciones es útil:
using System;
class Program
{
static void Main()
{
bool entradaValida = false;
int edad = 0;
while (!entradaValida)
{
try
{
Console.Write("Por favor, introduce tu edad: ");
string entrada = Console.ReadLine();
edad = int.Parse(entrada);
if (edad < 0 || edad > 120)
{
Console.WriteLine("La edad debe estar entre 0 y 120 años.");
continue;
}
entradaValida = true;
}
catch (FormatException)
{
Console.WriteLine("Error: Debes introducir un número entero.");
}
catch (OverflowException)
{
Console.WriteLine("Error: El número es demasiado grande o pequeño.");
}
}
Console.WriteLine($"Tu edad es: {edad} años");
}
}
En este ejemplo, usamos un bucle para solicitar repetidamente la edad del usuario hasta que se introduzca un valor válido. El bloque try-catch nos permite manejar diferentes tipos de errores que pueden ocurrir durante la conversión.
El manejo de excepciones con try-catch es una herramienta fundamental para crear aplicaciones robustas en C#. Te permite anticipar y responder a situaciones de error de manera elegante, mejorando la experiencia del usuario y evitando que tu programa se detenga inesperadamente.
Múltiples catch y finally
En situaciones reales de programación, los errores pueden ser de diversos tipos y requerir diferentes respuestas. C# nos permite manejar distintos tipos de excepciones de manera específica mediante el uso de múltiples bloques catch. Además, el bloque finally nos proporciona un mecanismo para ejecutar código independientemente de si ocurre una excepción o no.
Múltiples bloques catch
Cuando trabajamos con código que puede generar diferentes tipos de excepciones, es útil tratarlas de manera específica:
try
{
// Código que podría generar diferentes tipos de excepciones
}
catch (FormatException ex)
{
// Se ejecuta si ocurre un error de formato
}
catch (DivideByZeroException ex)
{
// Se ejecuta si ocurre una división por cero
}
catch (Exception ex)
{
// Se ejecuta para cualquier otro tipo de excepción
}
El orden de los bloques catch es crucial. C# evalúa los bloques catch en el orden en que aparecen, y ejecuta el primero que coincida con el tipo de excepción lanzada. Por esta razón, siempre debemos colocar las excepciones más específicas primero y las más generales después.
Veamos un ejemplo práctico:
using System;
class Program
{
static void Main()
{
Console.WriteLine("Calculadora simple");
try
{
Console.Write("Introduce el primer número: ");
int num1 = int.Parse(Console.ReadLine());
Console.Write("Introduce el segundo número: ");
int num2 = int.Parse(Console.ReadLine());
int resultado = num1 / num2;
Console.WriteLine($"El resultado de {num1} / {num2} es: {resultado}");
}
catch (FormatException)
{
Console.WriteLine("Error: Debes introducir números enteros válidos.");
}
catch (DivideByZeroException)
{
Console.WriteLine("Error: No es posible dividir por cero.");
}
catch (OverflowException)
{
Console.WriteLine("Error: El número es demasiado grande o pequeño.");
}
catch (Exception ex)
{
Console.WriteLine($"Error inesperado: {ex.Message}");
}
}
}
En este ejemplo:
- Si el usuario introduce algo que no es un número, se lanzará una
FormatException
- Si el segundo número es cero, se lanzará una
DivideByZeroException
- Si el número es demasiado grande para un int, se lanzará una
OverflowException
- Cualquier otra excepción será capturada por el último catch
Captura de excepciones con filtros
A partir de C# 6.0, podemos usar filtros de excepciones con la palabra clave when
para añadir condiciones adicionales a nuestros bloques catch:
try
{
// Código que podría generar excepciones
}
catch (Exception ex) when (ex.Message.Contains("específico"))
{
// Solo se ejecuta si el mensaje de la excepción contiene "específico"
}
Esto nos permite un control más granular sobre qué excepciones manejar:
using System;
using System.IO;
class Program
{
static void Main()
{
try
{
string contenido = File.ReadAllText("datos.txt");
Console.WriteLine(contenido);
}
catch (FileNotFoundException ex) when (ex.FileName.Contains("datos"))
{
Console.WriteLine("El archivo de datos no se encuentra.");
}
catch (IOException ex) when (ex.Message.Contains("being used"))
{
Console.WriteLine("El archivo está siendo utilizado por otro proceso.");
}
catch (IOException)
{
Console.WriteLine("Error general de entrada/salida.");
}
}
}
El bloque finally
El bloque finally contiene código que se ejecutará siempre, independientemente de si ocurre una excepción o no. Es especialmente útil para liberar recursos o realizar tareas de limpieza:
try
{
// Código que podría generar excepciones
}
catch (Exception ex)
{
// Manejo de la excepción
}
finally
{
// Este código siempre se ejecuta
}
El bloque finally se ejecuta en los siguientes casos:
- Después del bloque try si no ocurre ninguna excepción
- Después del bloque catch si ocurre una excepción
- Incluso si hay una instrucción return dentro del try o catch
Veamos un ejemplo práctico con un escenario común: trabajar con archivos.
using System;
using System.IO;
class Program
{
static void Main()
{
StreamReader archivo = null;
try
{
archivo = new StreamReader("datos.txt");
string contenido = archivo.ReadToEnd();
Console.WriteLine(contenido);
}
catch (FileNotFoundException)
{
Console.WriteLine("No se encontró el archivo.");
}
catch (IOException)
{
Console.WriteLine("Error al leer el archivo.");
}
finally
{
// Cerramos el archivo incluso si hubo una excepción
if (archivo != null)
{
archivo.Close();
Console.WriteLine("Archivo cerrado correctamente.");
}
}
Console.WriteLine("Programa finalizado.");
}
}
En este ejemplo, el bloque finally garantiza que el archivo se cierre correctamente, incluso si ocurre un error durante la lectura. Esto es crucial para evitar fugas de recursos.
Patrón using como alternativa a finally
Para recursos que implementan la interfaz IDisposable
(como archivos, conexiones a bases de datos, etc.), C# ofrece una alternativa más elegante al patrón try-finally: la instrucción using:
using System;
using System.IO;
class Program
{
static void Main()
{
try
{
using (StreamReader archivo = new StreamReader("datos.txt"))
{
string contenido = archivo.ReadToEnd();
Console.WriteLine(contenido);
} // El archivo se cierra automáticamente al salir del bloque using
}
catch (FileNotFoundException)
{
Console.WriteLine("No se encontró el archivo.");
}
catch (IOException)
{
Console.WriteLine("Error al leer el archivo.");
}
Console.WriteLine("Programa finalizado.");
}
}
La instrucción using
garantiza que el método Dispose()
del objeto se llame automáticamente al salir del bloque, incluso si ocurre una excepción. Esto equivale a usar un bloque finally para cerrar o liberar el recurso.
Combinación de try-catch-finally
Podemos combinar estos elementos según nuestras necesidades. Un bloque try puede tener:
- Uno o más bloques catch
- Un bloque finally (opcional)
- Ambos (catch y finally)
using System;
class Program
{
static void Main()
{
Console.WriteLine("Inicio del programa");
try
{
Console.WriteLine("Dentro del bloque try");
int[] numeros = { 1, 2, 3 };
Console.WriteLine(numeros[5]); // Esto generará una excepción
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Error: Índice fuera de rango");
}
finally
{
Console.WriteLine("Este bloque siempre se ejecuta");
}
Console.WriteLine("Fin del programa");
}
}
La salida de este programa será:
Inicio del programa
Dentro del bloque try
Error: Índice fuera de rango
Este bloque siempre se ejecuta
Fin del programa
Excepciones anidadas
También podemos tener bloques try-catch-finally anidados. Esto es útil cuando necesitamos manejar excepciones en diferentes niveles:
using System;
class Program
{
static void Main()
{
try
{
Console.WriteLine("Bloque try externo");
try
{
Console.WriteLine("Bloque try interno");
throw new ArgumentException("Error de argumento");
}
catch (ArgumentException ex)
{
Console.WriteLine($"Catch interno: {ex.Message}");
throw; // Re-lanzamos la excepción
}
finally
{
Console.WriteLine("Finally interno");
}
}
catch (Exception ex)
{
Console.WriteLine($"Catch externo: {ex.Message}");
}
finally
{
Console.WriteLine("Finally externo");
}
}
}
La salida será:
Bloque try externo
Bloque try interno
Catch interno: Error de argumento
Finally interno
Catch externo: Error de argumento
Finally externo
Observa cómo se ejecutan ambos bloques finally, y cómo la excepción re-lanzada es capturada por el catch externo.
Mejores prácticas
Al trabajar con múltiples catch y finally, considera estas recomendaciones:
- Sé específico: Captura solo las excepciones que puedes manejar adecuadamente.
- Ordena correctamente: Coloca las excepciones más específicas primero.
- Usa finally para limpieza: Utiliza finally para liberar recursos, no para lógica de negocio.
- Considera using: Para recursos IDisposable, prefiere la instrucción using cuando sea posible.
- No atrapes todo silenciosamente: Evita catch vacíos que oculten errores sin manejarlos.
// Mal ejemplo (no hacer esto)
try
{
// Código
}
catch (Exception)
{
// Ignorar silenciosamente
}
// Mejor enfoque
try
{
// Código
}
catch (Exception ex)
{
// Registrar el error
Console.WriteLine($"Error: {ex.Message}");
// Posiblemente re-lanzar si no podemos manejarlo
throw;
}
El manejo adecuado de excepciones con múltiples catch y finally te permitirá crear aplicaciones más robustas que puedan recuperarse de errores y liberar recursos correctamente, mejorando tanto la experiencia del usuario como la integridad de tu sistema.
Lanzar con throw
En C#, además de capturar excepciones, también podemos crearlas y lanzarlas explícitamente cuando detectamos situaciones de error en nuestro código. La palabra clave throw
nos permite generar excepciones de forma controlada cuando identificamos condiciones que no deberían ocurrir en el flujo normal de nuestro programa.
Sintaxis básica de throw
La sintaxis para lanzar una excepción es muy sencilla:
throw new TipoDeExcepcion("Mensaje descriptivo del error");
Por ejemplo, si queremos lanzar una excepción cuando un parámetro no cumple con ciertos requisitos:
public void VerificarEdad(int edad)
{
if (edad < 0)
{
throw new ArgumentException("La edad no puede ser negativa");
}
Console.WriteLine($"La edad {edad} es válida");
}
En este ejemplo, si alguien intenta verificar una edad negativa, el método lanzará una excepción en lugar de continuar con la ejecución normal.
Cuándo usar throw
El lanzamiento de excepciones es útil en varias situaciones:
- Validación de parámetros: Cuando los argumentos de un método no cumplen con los requisitos esperados.
- Estados imposibles: Cuando el programa llega a un estado que no debería ser posible.
- Errores de lógica de negocio: Cuando se violan reglas específicas de la aplicación.
- Propagación de errores: Cuando queremos que un error de bajo nivel se convierta en uno más significativo.
Veamos un ejemplo más completo:
using System;
class Calculadora
{
public double Dividir(double numerador, double denominador)
{
if (denominador == 0)
{
throw new DivideByZeroException("No se puede dividir por cero");
}
return numerador / denominador;
}
public double CalcularRaizCuadrada(double numero)
{
if (numero < 0)
{
throw new ArgumentOutOfRangeException("numero", "No se puede calcular la raíz cuadrada de un número negativo");
}
return Math.Sqrt(numero);
}
}
class Program
{
static void Main()
{
Calculadora calc = new Calculadora();
try
{
// Probamos con un caso válido
double resultado1 = calc.Dividir(10, 2);
Console.WriteLine($"10 / 2 = {resultado1}");
// Probamos con un caso inválido
double resultado2 = calc.Dividir(5, 0);
Console.WriteLine($"5 / 0 = {resultado2}"); // Esta línea nunca se ejecutará
}
catch (DivideByZeroException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
try
{
// Probamos con un caso inválido
double raiz = calc.CalcularRaizCuadrada(-4);
}
catch (ArgumentOutOfRangeException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
Tipos comunes de excepciones para lanzar
C# proporciona muchas clases de excepciones predefinidas que podemos utilizar según el tipo de error:
- ArgumentException: Para argumentos inválidos en general.
- ArgumentNullException: Cuando un argumento que no debería ser null lo es.
- ArgumentOutOfRangeException: Cuando un argumento está fuera del rango permitido.
- InvalidOperationException: Cuando una operación no es válida en el estado actual.
- NotImplementedException: Para métodos que aún no están implementados.
- NotSupportedException: Para operaciones que no son compatibles.
public void ProcesarDatos(string[] datos)
{
if (datos == null)
{
throw new ArgumentNullException(nameof(datos), "El array de datos no puede ser null");
}
if (datos.Length == 0)
{
throw new ArgumentException("El array de datos no puede estar vacío", nameof(datos));
}
// Procesamiento normal...
}
Re-lanzamiento de excepciones
En ocasiones, queremos capturar una excepción, realizar alguna acción (como registrar el error) y luego volver a lanzarla para que sea manejada en un nivel superior. Hay dos formas de hacerlo:
- Re-lanzamiento simple: Mantiene la pila de llamadas original.
try
{
// Código que puede generar una excepción
}
catch (Exception ex)
{
// Registramos el error
Console.WriteLine($"Se ha registrado un error: {ex.Message}");
// Re-lanzamos la misma excepción manteniendo la pila de llamadas original
throw;
}
- Creación de una nueva excepción: Crea una nueva excepción con información adicional.
try
{
// Código que puede generar una excepción
}
catch (IOException ex)
{
// Creamos una nueva excepción con la original como InnerException
throw new ApplicationException("Error al procesar el archivo", ex);
}
La diferencia es importante:
throw;
mantiene la pila de llamadas original, lo que facilita la depuración.throw new Exception(...);
crea una nueva pila de llamadas, pero permite añadir contexto adicional.
Creación de excepciones personalizadas
Cuando los tipos de excepciones predefinidos no son suficientes, podemos crear nuestras propias clases de excepciones:
using System;
using System.Runtime.Serialization;
[Serializable]
public class UsuarioNoEncontradoException : Exception
{
public string Usuario { get; }
public UsuarioNoEncontradoException() : base() { }
public UsuarioNoEncontradoException(string message) : base(message) { }
public UsuarioNoEncontradoException(string message, Exception innerException)
: base(message, innerException) { }
public UsuarioNoEncontradoException(string message, string usuario)
: base(message)
{
Usuario = usuario;
}
// Constructor necesario para la serialización
protected UsuarioNoEncontradoException(SerializationInfo info, StreamingContext context)
: base(info, context) { }
}
Y podemos usarla así:
public Usuario BuscarUsuario(string nombreUsuario)
{
// Simulamos búsqueda en base de datos
if (nombreUsuario == "admin")
{
return new Usuario { Nombre = "Administrador", Id = 1 };
}
throw new UsuarioNoEncontradoException(
$"No se encontró el usuario con nombre '{nombreUsuario}'",
nombreUsuario);
}
Ejemplo práctico: Validación de datos
Veamos un ejemplo completo de cómo usar throw
para validar datos de entrada:
using System;
class Producto
{
private string _nombre;
private decimal _precio;
private int _stock;
public string Nombre
{
get => _nombre;
set
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("El nombre del producto no puede estar vacío");
}
_nombre = value;
}
}
public decimal Precio
{
get => _precio;
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value),
"El precio no puede ser negativo");
}
_precio = value;
}
}
public int Stock
{
get => _stock;
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value),
"El stock no puede ser negativo");
}
_stock = value;
}
}
public void Vender(int cantidad)
{
if (cantidad <= 0)
{
throw new ArgumentOutOfRangeException(nameof(cantidad),
"La cantidad a vender debe ser mayor que cero");
}
if (cantidad > _stock)
{
throw new InvalidOperationException(
$"No hay suficiente stock. Stock actual: {_stock}, Cantidad solicitada: {cantidad}");
}
_stock -= cantidad;
}
}
class Program
{
static void Main()
{
try
{
Producto laptop = new Producto();
laptop.Nombre = "Laptop HP";
laptop.Precio = 1200.50m;
laptop.Stock = 10;
Console.WriteLine($"Producto: {laptop.Nombre}, Precio: ${laptop.Precio}, Stock: {laptop.Stock}");
// Intentamos vender más de lo que hay en stock
laptop.Vender(15);
}
catch (ArgumentException ex)
{
Console.WriteLine($"Error de argumento: {ex.Message}");
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"Error de operación: {ex.Message}");
}
}
}
Mejores prácticas al lanzar excepciones
Para usar throw
de manera efectiva, considera estas recomendaciones:
- Sé específico: Usa el tipo de excepción más específico para el error.
- Mensajes claros: Incluye mensajes descriptivos que ayuden a entender y solucionar el problema.
- Incluye detalles relevantes: Añade información contextual como nombres de parámetros o valores.
- No abuses: Lanza excepciones solo para condiciones excepcionales, no para controlar el flujo normal.
- Documenta: Indica en la documentación del método qué excepciones puede lanzar.
/// <summary>
/// Transfiere dinero entre dos cuentas.
/// </summary>
/// <param name="origen">Cuenta de origen</param>
/// <param name="destino">Cuenta de destino</param>
/// <param name="monto">Monto a transferir</param>
/// <exception cref="ArgumentNullException">Si alguna cuenta es null</exception>
/// <exception cref="ArgumentOutOfRangeException">Si el monto es negativo o cero</exception>
/// <exception cref="InvalidOperationException">Si la cuenta origen no tiene fondos suficientes</exception>
public void Transferir(Cuenta origen, Cuenta destino, decimal monto)
{
if (origen == null)
throw new ArgumentNullException(nameof(origen));
if (destino == null)
throw new ArgumentNullException(nameof(destino));
if (monto <= 0)
throw new ArgumentOutOfRangeException(nameof(monto), "El monto debe ser positivo");
if (origen.Saldo < monto)
throw new InvalidOperationException("Fondos insuficientes para realizar la transferencia");
origen.Saldo -= monto;
destino.Saldo += monto;
}
Throw vs. return de códigos de error
Antes de las excepciones, era común devolver códigos de error para indicar problemas. Comparemos ambos enfoques:
// Enfoque con códigos de error
public bool TryDividir(double a, double b, out double resultado, out string error)
{
if (b == 0)
{
resultado = 0;
error = "No se puede dividir por cero";
return false;
}
resultado = a / b;
error = null;
return true;
}
// Uso:
if (TryDividir(10, 0, out double res, out string err))
{
Console.WriteLine($"Resultado: {res}");
}
else
{
Console.WriteLine($"Error: {err}");
}
// Enfoque con excepciones
public double Dividir(double a, double b)
{
if (b == 0)
{
throw new DivideByZeroException("No se puede dividir por cero");
}
return a / b;
}
// Uso:
try
{
double res = Dividir(10, 0);
Console.WriteLine($"Resultado: {res}");
}
catch (DivideByZeroException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
El enfoque con excepciones tiene varias ventajas:
- Separación de responsabilidades: El código de éxito y el de error están claramente separados.
- Propagación automática: Los errores se propagan automáticamente sin necesidad de verificar cada llamada.
- Información detallada: Las excepciones contienen más información sobre el error.
El uso adecuado de throw
te permitirá crear código más robusto y comunicar claramente las condiciones de error, mejorando tanto la calidad del código como la experiencia de desarrollo.
Otros ejercicios de programación de CSharp
Evalúa tus conocimientos de esta lección Excepciones con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
CRUD en C# de modelo Customer sobre una lista
Arrays y listas
Objetos
Excepciones
Eventos
Lambdas
Diccionarios en C#
Variables y constantes
Tipos de datos
Herencia
Operadores
Uso de consultas LINQ
Clases y encapsulación
Uso de consultas LINQ
Excepciones
Control de flujo
Eventos
Diccionarios
Tipos de datos
Conjuntos, colas y pilas
Lambdas
Conjuntos, colas y pilas
Uso de async y await
Tareas
Constructores y destructores
Operadores
Arrays y listas
Polimorfismo
Polimorfismo
Variables y constantes
Proyecto colecciones y LINQ en C#
Clases y encapsulación
Creación de proyecto C#
Uso de async y await
Funciones
Delegados
Delegados
Constructores y destructores
Objetos
Control de flujo
Funciones
Tareas
Proyecto sintaxis en C#
Herencia C Sharp
OOP en C Sharp
Diccionarios
Introducción a C#
Todas las lecciones de CSharp
Accede a todas las lecciones de CSharp y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A C#
Introducción Y Entorno
Creación De Proyecto C#
Introducción Y Entorno
Variables Y Constantes
Sintaxis
Tipos De Datos
Sintaxis
Operadores
Sintaxis
Control De Flujo
Sintaxis
Funciones
Sintaxis
Estructuras De Control Iterativo
Sintaxis
Interpolación De Strings
Sintaxis
Estructuras De Control Condicional
Sintaxis
Manejo De Valores Nulos
Sintaxis
Clases Y Encapsulación
Programación Orientada A Objetos
Objetos
Programación Orientada A Objetos
Constructores Y Destructores
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
Genéricos
Programación Orientada A Objetos
Métodos Virtuales Y Sobrecarga
Programación Orientada A Objetos
Clases Abstractas
Programación Orientada A Objetos
Interfaces
Programación Orientada A Objetos
Propiedades Y Encapsulación
Programación Orientada A Objetos
Métodos De Extensión
Programación Orientada A Objetos
Clases Y Objetos
Programación Orientada A Objetos
Clases Parciales
Programación Orientada A Objetos
Miembros Estáticos
Programación Orientada A Objetos
Tuplas Y Tipos Anónimos
Programación Orientada A Objetos
Arrays Y Listas
Colecciones Y Linq
Diccionarios
Colecciones Y Linq
Conjuntos, Colas Y Pilas
Colecciones Y Linq
Uso De Consultas Linq
Colecciones Y Linq
Linq Avanzado
Colecciones Y Linq
Colas Y Pilas
Colecciones Y Linq
Conjuntos
Colecciones Y Linq
Linq Básico
Colecciones Y Linq
Delegados Funcionales
Programación Funcional
Records
Programación Funcional
Expresiones Lambda
Programación Funcional
Linq Funcional
Programación Funcional
Fundamentos De La Programación Funcional
Programación Funcional
Pattern Matching
Programación Funcional
Testing Unitario Con Xunit
Testing
Excepciones
Excepciones
Delegados
Programación Asíncrona
Eventos
Programación Asíncrona
Lambdas
Programación Asíncrona
Uso De Async Y Await
Programación Asíncrona
Tareas
Programación Asíncrona
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la estructura básica y el flujo de ejecución de try-catch en C#.
- Aprender a manejar múltiples tipos de excepciones con bloques catch específicos y filtros.
- Entender el uso del bloque finally para liberar recursos y su relación con la instrucción using.
- Saber cómo lanzar excepciones con throw y crear excepciones personalizadas.
- Aplicar buenas prácticas en el manejo y lanzamiento de excepciones para escribir código robusto y mantenible.