Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
59m 46s
La gestión de excepciones es un aspecto crucial del desarrollo de aplicaciones robustas. El vídeo de Tim Corey sobre "Manejo de excepciones en C# - Cuándo atraparlas, dónde atraparlas y cómo atraparlas", ofrece una explicación detallada de qué son las excepciones, cómo manejarlas y dónde manejarlas.
El objetivo de este artículo es explicar el manejo de excepciones en C# utilizando el vídeo de Tim Corey. Se trata de una potente función que permite a los desarrolladores gestionar los errores y las condiciones excepcionales que surgen durante la ejecución de un programa. Mediante los bloques try, catch y finally, C# ofrece una forma estructurada de gestionar errores en tiempo de ejecución, registrar excepciones y mantener el flujo del programa.
Tim comienza explicando que muchos desarrolladores tienen una visión incorrecta de las excepciones y su gestión. Destaca la importancia de entender qué son las excepciones y dónde y cómo manejarlas adecuadamente para crear aplicaciones más robustas.
Tim crea una aplicación de consola en Visual Studio 2017 para demostrar el manejo de excepciones. Recomienda utilizar aplicaciones de consola para probar nuevos temas, ya que requieren una configuración mínima y es fácil trabajar con ellas.
using System;
namespace ExceptionsDemo
{
class Program
{
static void Main(string[] args)
{
// Placeholder for input and output operations
Console.ReadLine();
}
}
}Imports System
Namespace ExceptionsDemo
Module Program
Sub Main(args As String())
' Placeholder for input and output operations
Console.ReadLine()
End Sub
End Module
End NamespaceTim añade una biblioteca de clases a la solución para simular un escenario real en el que diferentes métodos se llaman entre sí.

Elimina la clase por defecto y crea una nueva clase llamada DemoCode.
public class DemoCode
{
// Method to retrieve a number based on the provided position
public int GetNumber(int position)
{
int[] numbers = { 1, 4, 7, 2 };
return numbers[position];
}
// Intermediate method calls GetNumber
public int ParentMethod(int position)
{
return GetNumber(position);
}
// Top-level method calls ParentMethod
public int GrandparentMethod(int position)
{
return ParentMethod(position);
}
}Public Class DemoCode
' Method to retrieve a number based on the provided position
Public Function GetNumber(position As Integer) As Integer
Dim numbers As Integer() = {1, 4, 7, 2}
Return numbers(position)
End Function
' Intermediate method calls GetNumber
Public Function ParentMethod(position As Integer) As Integer
Return GetNumber(position)
End Function
' Top-level method calls ParentMethod
Public Function GrandparentMethod(position As Integer) As Integer
Return ParentMethod(position)
End Function
End ClassLa clase DemoCode contiene métodos que se llaman entre sí, recuperando en última instancia un número de un array basado en la posición dada.
Tim explica que la aplicación está pensada para demostrar fallos más que éxitos. Introduce una excepción de fuera de límites al pasar una posición no válida al GrandparentMethod.
DemoCode demo = new DemoCode();
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");Dim demo As New DemoCode()
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")Si se ejecuta el código anterior con una posición no válida, se produce una IndexOutOfRangeException. Tim muestra cómo el depurador de Visual Studio resalta el problema y proporciona información detallada sobre la excepción.
Tim explica un error común que cometen los desarrolladores cuando aprenden por primera vez sobre los bloques try-catch. A menudo, los desarrolladores envuelven todo el bloque de código en el que esperan que se produzca una excepción, lo que puede dar lugar a una gestión inadecuada.
try
{
int output = 0;
output = numbers[position];
return output;
}
catch (Exception ex)
{
// Avoid returning default values that can mask the problem
return 0;
}Try
Dim output As Integer = 0
output = numbers(position)
Return output
Catch ex As Exception
' Avoid returning default values that can mask the problem
Return 0
End TryTim destaca que este enfoque es problemático porque oculta la excepción y continúa la ejecución con suposiciones incorrectas. Por ejemplo, devolver 0 como valor por defecto puede no ser apropiado y causar más problemas.
Tim subraya que las excepciones proporcionan información crítica sobre estados inesperados de la aplicación. Si la aplicación continúa en ese estado sin un tratamiento adecuado, puede dar lugar a más errores y corrupción de datos.
En lugar de tragarse las excepciones, es esencial manejarlas adecuadamente. He aquí un enfoque mejor:
try
{
return numbers[position];
}
catch (Exception ex)
{
// Log the exception or handle it appropriately
Console.WriteLine(ex.Message);
throw; // Re-throw the exception to be handled by a higher-level handler
}Try
Return numbers(position)
Catch ex As Exception
' Log the exception or handle it appropriately
Console.WriteLine(ex.Message)
Throw ' Re-throw the exception to be handled by a higher-level handler
End TryAl volver a lanzar la excepción, te aseguras de que el problema se propague y pueda tratarse en un nivel superior si es necesario.
Tim explica que, aunque algunas excepciones pueden gestionarse con elegancia sin bloquear la aplicación, es importante proporcionar información útil al usuario. Por ejemplo, mostrando un cuadro de mensaje o una notificación con la opción de reintentar la operación.
Tim muestra cómo utilizar la propiedad StackTrace del objeto de excepción para obtener información detallada sobre dónde se ha producido la excepción. Esto incluye la clase, el método y el número de línea, lo que es muy valioso para la depuración.
try
{
return numbers[position];
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
throw;
}Try
Return numbers(position)
Catch ex As Exception
Console.WriteLine(ex.StackTrace)
Throw
End TryLa propiedad StackTrace proporciona una traza completa de la pila de llamadas, lo que ayuda a los desarrolladores a localizar exactamente el problema.
Tim explica que el manejo adecuado de las excepciones no consiste únicamente en capturarlas, sino también en saber dónde colocar los bloques try-catch. La clave está en situar los bloques try-catch en un nivel en el que se disponga de contexto suficiente para gestionar la excepción adecuadamente.
Colocar un bloque try-catch en lo más profundo de la pila de llamadas a menudo no permite gestionar la excepción con eficacia porque se carece del contexto de las operaciones de nivel superior.
// Deep level exception handling (not ideal)
try
{
return numbers[position];
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}' Deep level exception handling (not ideal)
Try
Return numbers(position)
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw
End TryColocar el bloque try-catch en el nivel superior, como en la interfaz de usuario o en el punto de entrada de la aplicación, permite gestionar las excepciones con el contexto completo de la operación.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryDe este modo, podrá ofrecer mensajes más informativos al usuario y decidir si la aplicación puede seguir ejecutándose o si debe finalizar.
Tim hace hincapié en la importancia de la información de seguimiento de pila a la hora de diagnosticar excepciones. El seguimiento de la pila proporciona un historial detallado de las llamadas, mostrando dónde se produjo la excepción y la cadena de llamadas a métodos que condujeron a ella.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryEl resultado proporciona la ubicación exacta de la excepción y la ruta seguida a través del código, lo que facilita la depuración y la solución del problema.
Tim demuestra cómo manejar la lógica en el nivel adecuado. Por ejemplo, si un método es responsable de abrir y cerrar una conexión a una base de datos, debe manejar excepciones para garantizar que los recursos se gestionan correctamente.
public int GrandparentMethod(int position)
{
try
{
Console.WriteLine("Open database connection");
int output = ParentMethod(position);
Console.WriteLine("Close database connection");
return output;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Ensure the exception is propagated
}
}Public Function GrandparentMethod(position As Integer) As Integer
Try
Console.WriteLine("Open database connection")
Dim output As Integer = ParentMethod(position)
Console.WriteLine("Close database connection")
Return output
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Ensure the exception is propagated
End Try
End FunctionEn este ejemplo, si se produce una excepción, la conexión a la base de datos no se cierra correctamente, lo que puede provocar una fuga de recursos. Añadiendo un bloque try-catch, puede asegurarse de que la conexión se cierra incluso si se produce una excepción.
Tim presenta el bloque finally, que garantiza que cierto código se ejecute independientemente de que se produzca una excepción. Esto es particularmente útil para la limpieza de recursos, como el cierre de conexiones de bases de datos.
public int GrandparentMethod(int position)
{
try
{
Console.WriteLine("Open database connection");
int output = ParentMethod(position);
return output;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Re-throw the exception to ensure it's handled by a higher-level handler
}
finally
{
Console.WriteLine("Close database connection");
}
}Public Function GrandparentMethod(position As Integer) As Integer
Try
Console.WriteLine("Open database connection")
Dim output As Integer = ParentMethod(position)
Return output
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Re-throw the exception to ensure it's handled by a higher-level handler
Finally
Console.WriteLine("Close database connection")
End Try
End FunctionEl bloque finally se ejecuta después de los bloques try y catch, asegurando que la conexión se cierra incluso si se lanza una excepción.
Tim explica la importancia de volver a lanzar excepciones para pasarlas a la pila de llamadas. De este modo, los gestores de nivel superior podrán procesar las excepciones adecuadamente.
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Re-throws the exception to be handled by the calling method
}Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Re-throws the exception to be handled by the calling method
End TryVolver a lanzar la excepción con throw; garantiza que se conserve el seguimiento completo de la pila, lo que proporciona un contexto valioso para la depuración.
Tim demuestra cómo las excepciones burbujean a través de la pila de llamadas. Cada método comprueba si hay un bloque try-catch y, o bien maneja la excepción, o bien se la pasa a quien la llama.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryEn este ejemplo, el GrandparentMethod captura la excepción, la registra y la vuelve a lanzar. A continuación, el bloque try-catch de nivel superior de la aplicación de consola gestiona la excepción y muestra el mensaje de error y el seguimiento de la pila.
Tim destaca varios errores comunes que cometen los desarrolladores al gestionar excepciones:
Usando throw ex;:
Reescribir el stack trace y perder un contexto valioso.
Ejemplo:
catch (Exception ex)
{
// Incorrect
throw ex; // Rewrites stack trace
}
Lanzamiento de una nueva excepción:
Creación de una nueva excepción con un mensaje personalizado, pero pérdida del seguimiento de pila original.
Ejemplo:
catch (Exception ex)
{
// Incorrect
throw new Exception("I blew up");
}
Tim explica cómo crear una nueva excepción conservando el rastro de pila original. Esto puede ser útil cuando se desea proporcionar un mensaje de error más significativo o un tipo de excepción diferente, pero conservando el contexto del error original.
catch (Exception ex)
{
throw new ArgumentException("You passed in bad data", ex);
}Catch ex As Exception
Throw New ArgumentException("You passed in bad data", ex)
End CatchAl pasar la excepción original (ex) como excepción interna, se mantiene el rastro de pila original, que es crucial para la depuración.
Tim muestra cómo acceder al mensaje de la excepción original y al seguimiento de la pila al crear una nueva excepción.
catch (Exception ex)
{
Console.WriteLine("You passed in bad data");
Console.WriteLine(ex.StackTrace);
throw new ArgumentException("You passed in bad data", ex);
}Catch ex As Exception
Console.WriteLine("You passed in bad data")
Console.WriteLine(ex.StackTrace)
Throw New ArgumentException("You passed in bad data", ex)
End TryEsto garantiza que la excepción lanzada a la pila contenga tanto el nuevo mensaje como los detalles de la excepción original.
Tim proporciona un método para recorrer en bucle todas las excepciones internas y extraer sus mensajes y rastros de pila.
catch (Exception ex)
{
Exception inner = ex;
while (inner != null)
{
Console.WriteLine(inner.StackTrace);
inner = inner.InnerException;
}
throw;
}Catch ex As Exception
Dim inner As Exception = ex
While inner IsNot Nothing
Console.WriteLine(inner.StackTrace)
inner = inner.InnerException
End While
Throw
End TryEste bucle itera a través de cada excepción interna, imprimiendo su rastro de pila, asegurándose de que se tienen en cuenta todas las capas de excepciones.
Tim explica cómo manejar distintos tipos de excepciones utilizando varios bloques catch. Esto permite un tratamiento específico basado en el tipo de excepción.
try
{
// Code that might throw an exception
}
catch (ArgumentException ex)
{
Console.WriteLine("You gave us bad information. Bad user!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
' Code that might throw an exception
Catch ex As ArgumentException
Console.WriteLine("You gave us bad information. Bad user!")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryEn este ejemplo, la excepción ArgumentException se gestiona específicamente imprimiendo un mensaje personalizado, mientras que todas las demás excepciones se devuelven a un gestor general que imprime el mensaje de excepción y el seguimiento de la pila.

Tim hace hincapié en la importancia del orden cuando se utilizan varios bloques de captura. Las excepciones más específicas deben capturarse en primer lugar, seguidas de las excepciones más generales.
try
{
// Code that might throw an exception
}
catch (ArgumentException ex)
{
Console.WriteLine("You gave us bad information. Bad user!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
' Code that might throw an exception
Catch ex As ArgumentException
Console.WriteLine("You gave us bad information. Bad user!")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TrySi aparece un bloque de captura más general antes que uno específico, este último capturará todas las excepciones y nunca se llegará al bloque de captura específico, lo que provocará errores de compilación.
La guía avanzada de Tim Corey video sobre el manejo de excepciones en C# cubre técnicas críticas para crear nuevas excepciones, preservar las trazas de pila y utilizar múltiples bloques catch de forma eficaz. Siguiendo sus mejores prácticas, los desarrolladores pueden crear aplicaciones robustas que manejen las excepciones con elegancia y proporcionen valiosa información de depuración.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy