Manejo de errores en C#: try/catch y técnicas avanzadas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Manejo de errores en C#: de try/catch a técnicas profesionales



En el mundo del desarrollo industrial con C# y .NET, el manejo de errores no es solo la construcción try/catch. Es toda una filosofía que determina la fiabilidad, legibilidad y tolerancia a fallos de su código. A nivel avanzado, el desarrollador no solo debe capturar excepciones, sino también diseñarlas, filtrarlas, registrarlas y restaurar el estado de la aplicación de manera competente. En este artículo, analizaremos los aspectos clave del manejo de errores en C# que le ayudarán a escribir un código más profesional y de mayor calidad.



1. Más allá de try/catch/finally: gestión de recursos y contexto



La construcción básica try-catch-finally es conocida por todos, pero veámosla desde otro ángulo. El objetivo principal del bloque finally es la liberación garantizada de recursos, incluso si ocurre una excepción. En versiones modernas de C#, a menudo se usa using para esto, pero finally sigue siendo indispensable cuando se trabaja con recursos no administrados o lógica de finalización compleja.



public void ProcessFile(string path){    FileStream? fileStream = null;    try    {        fileStream = File.OpenRead(path);        // Lógica de procesamiento del archivo    }    catch (FileNotFoundException ex)    {        // Manejo específico: archivo no encontrado        Log.Error($"Archivo {path} no encontrado: {ex.Message}");        throw; // Relanza la excepción, conservando la pila de llamadas    }    catch (UnauthorizedAccessException)    {        Log.Warn($"Sin acceso al archivo: {path}");        // Se puede realizar una acción alternativa sin relanzar la excepción        return;    }    finally    {        // Liberación garantizada del recurso        fileStream?.Dispose();    }}


Observe el uso de throw; (sin argumento) — este es un punto clave. A diferencia de throw ex;, la construcción throw; conserva la pila de llamadas original, lo cual es crítico para la depuración. Nunca use throw ex; en proyectos reales, ya que destruye la información sobre el lugar de origen del error original.



2. Excepciones personalizadas: diseñando un modelo de dominio de errores



En aplicaciones grandes, las excepciones estándar de .NET a menudo no son suficientes. Crear sus propias clases de excepción le permite transmitir con precisión el contexto del error y simplifica el manejo en niveles superiores. Una buena excepción personalizada debe ser serializable, contener un mensaje significativo y llevar información adicional (por ejemplo, un identificador de entidad).



[Serializable]public class OrderProcessingException : Exception{    public int OrderId { get; }    public string FaultyStep { get; }

public OrderProcessingException(int orderId, string faultyStep, string message) : base(message) { OrderId = orderId; FaultyStep = faultyStep; }

public OrderProcessingException(int orderId, string faultyStep, string message, Exception inner) : base(message, inner) { OrderId = orderId; FaultyStep = faultyStep; }

// Constructor para deserialización protected OrderProcessingException( System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { OrderId = info.GetInt32(nameof(OrderId)); FaultyStep = info.GetString(nameof(FaultyStep)) ?? string.Empty; }

public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { base.GetObjectData(info, context); info.AddValue(nameof(OrderId), OrderId); info.AddValue(nameof(FaultyStep), FaultyStep); }}

// Usopublic void ValidateOrder(int orderId){ try {

Blogs

Book Recommendations