Cuando el código de nuestro programa produce un error o una situación no esperada que se traduce en un fallo se produce una excepción.
.NET Framework ofrece gestión estructurada de excepciones, es decir, que podemos gestionar las excepciones de manera jerárquica en nuestro código, capturándolas en la rutina que las produce o en cualquier otro punto de la pila de llamadas de ésta (es decir, las excepciones "convergen" hacia los niveles superiores de la pila).
La estructura Try-Catch-Finally (VB) o try-catch-finally (C#) nos permite gestionar las excepciones dentro del bloque "catch" especificando el tipo concreto de excepción que queremos gestionar, pudiendo así ser lo más específicos posible a la hora de hacerlo. Por ello la plataforma ofrece multitud de tipos de excepciones especializadas para indicar situaciones concretas: división por cero, argumentos no válidos, error de I/O, etc... Y también nos permite crear nuestras propias excepciones y lanzarlas con throw.
Así podemos generar excepciones propias para responder ante situaciones controladas por nuestro código o notificar situaciones al código que haga uso de nuestras funciones. Esto último contrasta enormemente con la programación tradicional en otros lenguajes, en los que para marcar el éxito o fracaso de ejecutar una determinada función se solían usar valores devueltos por las propias funciones (por ejemplo, si devuelve un 0 es que todo ha ido bien, pero en caso contrario devuelvo un numerito para indicar el error). Si no me crees fíjate en la API de Windows por ejemplo, que es un infierno con estas cosas :-)
Eso es una mala práctica y gracias a los dioses se ha terminado por virtud de la gestión estructurada de excepciones. Y esto, algunos programadores "con solera" (o sea, viejos), lo tenemos muy a flor de piel ;-))
Pero... ¿Cómo genero mis propias excepciones?
Las excepciones son clases normales y corrientes que heredan de una clase base especial de la plataforma: Exception.
Por lo tanto podemos crear nuevas excepciones que hereden de otras y adaptarlas así a nuestras necesidades. Lo habitual sin embargo es heredar directamente de la clase base Exception mencionada.
Lo único que debemos tener en cuenta a la hora de crear nuestras propias excepciones son algunas convenciones que debemos seguir (no son obligatorias, pero siempre se hace así por convención para facilitar a otros programadores el trabajo):
1.- Termina el nombre de tu clase de excepción personalizada con el sufijo Exception.
2.- Haz que la excepción sea serializable. Si heredas de Exception ya no lo tienes que hacer tú.
3.- Implementa los tres constructores básicos: sin parámetros, con un mensaje como parámetro y un tercero con posibilidad de pasar una excepción interna anidada también. Insisto, no es necesario, pero sí recomendable.
Es muy fácil. Por ejemplo, imagin¡emos que queremos crear una excepción personalizada para señalar que un valor no puede ser negativo (por poner un ejemplo básico). La definición de una clase excepción para gestionar esta situación sería:
public class ValorNegativoException : Exception
{
public ValorNegativoException() : base("No se admite un valor negativo") //Este es el mensaje por defecto, asignado a la clase base
{
}
public ValorNegativoException(string Mensaje) : base(Mensaje)
{
}
public ValorNegativoException(string Mensaje, Exception anidada) : base(Mensaje, anidada)
{
}
}
¡Listo!
Ahora ya podemos lanzar una excepción de este tipo usando la instrucción throw, así por ejemplo:
ValorNegativoException miExcep = new ValorNegativoException("No puedes usar valores negativos. ¡En qué piensas! :-)");
throw miExcep;
Y capturarla de la manera habitual dentro de un catch, ya que es una excepción normal como las propias de .NET.
¡Espero que te resulte útil!