Gestión de excepciones
La clase Exception
En cualquier aplicación, incluso probada y depurada, es posible encontrar errores de ejecución. Por ejemplo, si la aplicación necesita un recurso de red y este no está disponible, el error se debe interceptar y tratar. Los errores no solo se deben al código de la aplicación. También hay que tener presente el entorno de ejecución para gestionar correctamente los errores.
El Framework .NET proporciona una jerarquía de clases que representa los diferentes tipos de errores que se pueden producir. Todas estas clases provienen, de manera más o menos directa, de la clase base Exception, que contiene la información sobre el error que se ha producido, como el mensaje, el origen, la traza y el error original. Aunque la clase Exception es muy general, no querrá gestionar errores de este tipo. Existen dos clases derivadas que permiten separar los tipos de errores:
-
System.SystemException: esta clase se usa en los errores que normalmente se crean por el Framework .NET. Clases más específicas derivadas, como System.ArgumentException cuando un método tiene argumentos inválidos, o System.UnauthorizedAccessException cuando hay un problema de permisos.
-
System.ApplicationException: esta clase sirve de clase base para crear excepciones personalizadas propias de la aplicación. Es idéntica a la clase System.SystemException, y su objetivo...
La creación de excepciones personalizadas
Los tipos de excepciones que proporciona el Framework .NET no se corresponden obligatoriamente con los requerimientos de una aplicación que necesita un tipo de excepción que contenga campos específicos. La creación de excepciones personalizadas se lleva a cabo creando un nuevo tipo que herede de la clase System.ApplicationException.
Cree una nueva clase llamada ProjectException en la carpeta Library del proyecto. Esta nueva clase deriva del tipo System.ApplicationException y contiene una propiedad que permite almacenar el proyecto actual, cuando se desencadena el error:
public class ProjectException: ApplicationException
{
public Project Project { get; protected set; }
public ProjectException(Project project)
: base()
{
this.Project = project;
}
public ProjectException(Project project, string mensaje)
: base(mensaje)
{
this.Project = project;
}
public ProjectException(Project project, string mensaje,
Exception innerException)
...
El desencadenamiento de excepciones
Por lo general, el sistema desencadena una excepción, pero puede necesitar desencadenar una excepción más específica o detallada para tratarla más arriba en la pila de llamadas.
Observe el descriptor de acceso set de la propiedad SendDelay, de la clase ProjectSettings:
public int SendDelay
{
get { return this.sendDelay; }
set
{
if (value < 0)
throw new ArgumentException("El valor debe ser
superior o igual a 0.", "Intervalo de envío ");
if (this.sendDelay != value)
{
this.sendDelay = value;
this.HasChanged = true;
}
}
}
Cuando se asigna un valor, este se comprueba para determinar si es superior o igual a cero. El Intervalo de envío se corresponde con el tiempo de espera entre dos envíos de email. Por tanto, este número debe ser estrictamente mayor o igual a cero. En caso contrario, se genera una excepción del tipo ArgumentException:
throw new ArgumentException("El...
La intercepción y gestión de excepciones
Las excepciones forman parte del ciclo de vida de una aplicación. Como no se pueden evitar, es imprescindible interceptarlas y gestionarlas de una manera que no impida a la aplicación continuar su ejecución. El bloque try ... catch ... finally permite interceptar y tratar errores:
try
{
Instrucciones.
}
catch
{
Instrucciones de gestión de un error.
}
finally
{
Instrucciones que siempre se ejecutan.
}
La parte try contiene las instrucciones que pueden desencadenar un error. Si una excepción se desencadena directamente con una instrucción throw o desde la pila de llamadas, la ejecución pasa inmediatamente a la parte catch para tratar el error. Independientemente de si se produce una excepción o no, la parte finally siempre se ejecuta.
Los bloques finally contienen las instrucciones que siempre se ejecutan, bajo en cualquier circunstancia. En este bloque es donde se deben liberar los recursos e insertar los datos.
Cuando una excepción se desencadena, hay disponible una referencia al objeto Exception y se puede capturar en la parte catch:
try
{
Project = new Library.Project();
Project.ProjectSettings.SendDelay = -1;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Todas las excepciones derivan de System.Exception, el bloque catch del ejemplo anterior tratará todos errores. Es posible especificar un tipo más preciso para gestionar el error de una manera diferente:
catch (ArgumentException ex)
{
MessageBox.Show(ex.Message);
Project.ProjectSettings.SendDelay = 0;
}
Un controlador de errores puede contener varias partes catch. Solo se ejecuta una por cada excepción, en función del tipo de la misma:
try
{
Project = new Library.Project();
Project.ProjectSettings.SendDelay = -1;
}
catch (ArgumentException ex)
{
MessageBox.Show(ex.Message); ...