Manejo de Excepciones
## Objetivos de Aprendizaje
- Comprender tipos de excepciones
- Usar try, catch, finally
- Lanzar excepciones personalizadas
- Manejar excepciones con gracia
## ¿Qué es una Excepción?
Un evento que interrumpe el flujo normal del programa:
```csharp
class Program
{
static void Main()
{
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers[5]); // ¡IndexOutOfRangeException!
}
}
```
## Jerarquía de Excepciones
```text
Exception
├── SystemException
│ ├── ArgumentException
│ ├── IndexOutOfRangeException
│ ├── NullReferenceException
│ └── InvalidOperationException
├── IOException
│ ├── FileNotFoundException
│ └── DirectoryNotFoundException
├── FormatException
├── OverflowException
└── ... (muchas más)
```
## Try-Catch
### Sintaxis Básica
```csharp
try
{
int result = 10 / 0; // Podría lanzar excepción
}
catch (ArithmeticException ex)
{
Console.WriteLine("¡No se puede dividir por cero!");
Console.WriteLine(ex.Message);
}
```
### Múltiples Catch
```csharp
try
{
int[] arr = new int[5];
arr[10] = 100;
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine("¡Error de índice de arreglo!");
}
catch (ArithmeticException ex)
{
Console.WriteLine("¡Error matemático!");
}
catch (Exception ex)
{
Console.WriteLine("Error genérico: " + ex.Message);
}
```
### Orden de Catch
Lo más específico primero, luego lo general:
```csharp
try
{
// código
}
catch (NullReferenceException ex) // Específico primero
{
// manejar
}
catch (RuntimeException ex) // Luego lo más general
{
// manejar
}
catch (Exception ex) // Finalmente, lo más general
{
// manejar
}
```
## Bloque Finally
### Siempre Se Ejecuta
```csharp
StreamReader? reader = null;
try
{
reader = new StreamReader("file.txt");
string content = reader.ReadToEnd();
Console.WriteLine(content);
}
catch (FileNotFoundException)
{
Console.WriteLine("Archivo no encontrado");
}
catch (IOException ex)
{
Console.WriteLine("Error de E/S: " + ex.Message);
}
finally
{
// Siempre se ejecuta, incluso si se lanza excepción
reader?.Dispose();
}
```
### Try-with-resources (C# 8+)
```csharp
// El compilador genera el bloque finally automáticamente
try
{
using var reader = new StreamReader("file.txt");
string content = reader.ReadToEnd();
Console.WriteLine(content);
}
catch (FileNotFoundException)
{
Console.WriteLine("Archivo no encontrado");
}
// reader se disposing automáticamente
```
## Lanzar Excepciones
### Palabra Clave throw
```csharp
public static void ValidateAge(int age)
{
if (age < 0)
{
throw new ArgumentException("La edad no puede ser negativa");
}
if (age > 150)
{
throw new ArgumentException("La edad es muy alta");
}
}
```
### Tipos Comunes de Excepciones
| Tipo | Cuándo Lanzar |
|------|---------------|
| ArgumentException | Argumento inválido |
| ArgumentNullException | Argumento null |
| InvalidOperationException | Estado inválido |
| NotSupportedException | Operación no soportada |
## Excepciones Personalizadas
### Definir Clase de Excepción
```csharp
public class ValidationException : Exception
{
public ValidationException() { }
public ValidationException(string message) : base(message) { }
public ValidationException(string message, Exception inner)
: base(message, inner) { }
}
public class InvalidEmailException : ValidationException
{
public InvalidEmailException(string email)
: base($"Email inválido: {email}") { }
}
```
### Usar Excepción Personalizada
```csharp
public static void RegisterUser(string email)
{
if (!email.Contains("@"))
{
throw new InvalidEmailException(email);
}
// lógica de registro
}
// Manejo
try
{
RegisterUser("inválido");
}
catch (InvalidEmailException ex)
{
Console.WriteLine(ex.Message); // Email inválido: inválido
}
```
## Filtros de Excepciones (C# 6+)
### Cláusula when
```csharp
try
{
// código que podría lanzar excepción
}
catch (Exception ex) when (ex is ArgumentException or FormatException)
{
Console.WriteLine("Argumento o formato inválido");
}
catch (Exception ex) when (ex.Message.Contains("específico"))
{
Console.WriteLine("Ocurrió un error específico");
}
```
## Excepciones Comunes de Runtime
```csharp
// NullReferenceException
string? str = null;
str.Length; // NRE
// IndexOutOfRangeException
int[] arr = { 1, 2 };
arr[5] = 10; // IOR
// DivideByZeroException
int x = 10 / 0; // DBZ
// FormatException
int.Parse("abc"); // FP
// InvalidCastException
object obj = "hello";
int num = (int)obj; // ICE
// OverflowException
checked
{
int i = int.MaxValue;
i++; // OE
}
```
## Propiedades de Excepciones
```csharp
try
{
RiskyOperation();
}
catch (Exception ex)
{
ex.Message; // Descripción breve
ex.StackTrace; // Pila de llamadas
ex.InnerException; // Excepción causante
ex.GetType(); // Tipo de excepción
}
```
## Mejores Prácticas
### Hacer
```csharp
// Capturar excepciones específicas
try
{
string content = File.ReadAllText("file.txt");
}
catch (FileNotFoundException)
{
// Manejar excepción específica
}
// Limpiar con try-with-resources
try
{
using var connection = new DatabaseConnection();
// usar conexión
}
// Registrar y posiblemente relanzar
try
{
DoSomething();
}
catch (Exception ex)
{
Logger.Error("Falló", ex);
throw; // Relanzar original
}
```
### No Hacer
```csharp
// No tragar excepciones
try
{
DoSomething();
}
catch (Exception)
{
// ¡No hacer nada oculta bugs!
}
// No capturar sin acción
try
{
DoSomething();
}
catch (Exception ex)
{
Console.WriteLine(ex); // Al menos registrarlo
}
// No capturar todo
try
{
DoSomething();
}
catch // Catch vacío - ¡malo!
{
}
```
## Relanzar Excepciones
### throw vs throw
```csharp
catch (Exception ex)
{
Log(ex);
throw ex; // Reinicia la pila de llamadas a esta ubicación
}
catch (Exception ex)
{
Log(ex);
throw; // Preserva la pila de llamadas original (preferido)
}
```
## Resumen
- Las excepciones interrumpen el flujo normal
- try-catch-finally maneja excepciones
- finally siempre se ejecuta (o usar try-with-resources)
- throw lanza una excepción
- Las excepciones personalizadas extienden Exception
- Capturar excepciones específicas primero
- Filtros de excepciones: `catch when (condición)`
- Nunca tragar excepciones silenciosamente
- Usar `throw;` para relanzar con pila de llamadas preservada
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →