Está en la página 1de 31

EXCEPCIONES

Unidad 5
Excepciones
 Es posible que, al ejecutar un programa, se presenten
errores no esperados que alteren el funcionamiento del
mismo o incluso obligando a su finalización. Estos errores
no tienen por qué deberse a errores de programación, sino
que también pueden aparecer por un uso no esperado del
programa por parte del usuario (introducir datos no
permitidos, indicar un archivo no existente...).
 Podemos evitar los errores prediciendo futuras entradas de
datos erróneas o bien podemos tratarlos cuando surjan. Para
ello, la Plataforma .NET suministra la clase Exception del
espacio de nombres System.
Excepciones y control de excepciones

 Las características de control de excepciones del


lenguaje C# proporcionan una manera de afrontar
cualquier situación inesperada o excepcional que se
presente mientras se ejecuta un programa. El
control de excepciones utiliza las palabras clave
try, catch y finally para intentar acciones que
podrían no realizarse correctamente, controlar
errores y limpiar los recursos después.
Se deben identificar 3 bloques de código cuando se
trabaja con excepciones :

 El bloque de código que debe usar el


procesamiento de excepciones.

 Un bloque de código que se ejecuta si se encuentra


una excepción mientras se procesa el primer bloque
de código.

 Un bloque de código opcional que se ejecuta


después de que se procese la excepción.
Información general sobre excepciones

 Las excepciones son tipos que se derivan en última instancia de System.Exception.


 Utilice un bloque try alrededor de las instrucciones que puedan generar excepciones.
 Cuando se produce una excepción dentro del bloque try, el flujo de control salta al primer controlador de
excepciones asociado que se encuentre en cualquier parte de la pila de llamadas. En C#, la palabra clave
catch se utiliza para definir un controlador de excepciones.
 Si no hay un controlador de excepciones para una excepción determinada, el programa deja de ejecutarse
y presenta un mensaje de error.
 No detecte una excepción a menos que pueda controlarla y dejar la aplicación con un estado conocido. Si
detecta una excepción System.Exception, vuelva a producirla mediante la palabra clave throw al final del
bloque catch.
 Si un bloque catch define una variable de excepción, puede utilizar dicho bloque para obtener más
información sobre el tipo de excepción que se ha producido.
 Un programa que utiliza la palabra clave throw puede generar explícitamente excepciones.
 Los objetos de excepción contienen información detallada sobre el error, tal como el estado de la pila de
llamadas y una descripción de texto del error.
 El código de un bloque finally se ejecuta aunque se produzca una excepción. Use un bloque finally para
liberar recursos, por ejemplo, para cerrar las secuencias o archivos que se abrieron en el bloque try.
Ventajas
 Claridad: El uso de códigos especiales para informar de error suele dificultar la legibilidad del
fuente en tanto que se mezclan las instrucciones propias de la lógica del mismo con las
instrucciones propias del tratamiento de los errores que pudiesen producirse durante su
ejecución. Por ejemplo:
 
int resultado = obj.Método();
if (resultado == 0) // Sin errores al ejecutar obj.Método();
{...}
else if (resultado == 1) // Tratamiento de error de código 1
{...}
else if (resultado == 2) // Tratamiento de error de código 2
...

Como se verá, utilizando excepciones es posible escribir el código como si nunca se fuesen a
producir errores y dejar en una zona aparte todo el código de tratamiento de errores, lo que
contribuye a facilitar la legibilidad de los fuentes.
Ventajas
 Más información: A partir del valor de un código de error
puede ser difícil deducir las causas del mismo y conseguirlo
muchas veces implica tenerse que consultar la documentación
que proporcionada sobre el método que lo provocó, que puede
incluso que no especifique claramente su causa.
 
Por el contrario, una excepción es un objeto que cuenta con
campos que describen las causas del error y a cuyo tipo suele
dársele un nombre que resuma claramente su causa. Por ejemplo,
para informar errores de división por cero se suele utilizar una
excepción predefinida de tipo DivideByZeroException en cuyo
campo Message se detallan las causas del error producido.
Ventajas
 Tratamiento asegurado: Cuando se utilizan códigos de error
nada obliga a tratarlos en cada llamada al método que los pueda
producir, e ignorarlos puede provocar más adelante en el código
comportamientos inesperados de causas difíciles de descubrir.
 
Cuando se usan excepciones siempre se asegura que el
programador trate toda excepción que pueda producirse o que,
si no lo hace, se aborte la ejecución de la aplicación
mostrándose un mensaje indicando dónde se ha producido el
error.
 
Excepciones derivadas de System.Exception que se corresponden con los errores más
comunes que pueden surgir durante la ejecución de una aplicación.

Tipo de la excepción Causa de que se produzca la excepción


ArgumentException Pasado argumento no válido (base de excepciones de argumentos)
ArgumentNullException Pasado argumento nulo
ArgumentOutOfRangeException Pasado argumento fuera de rango
ArrayTypeMistmatchException Asignación a tabla de elemento que no es de su tipo
COMException Excepción de objeto COM
DivideByZeroException División por cero
IndexOutOfRangeException Índice de acceso a elemento de tabla fuera del rango válido (menor que cero o mayor que el tamaño de la
tabla)
InvalidCastException Conversión explícita entre tipos no válida
InvalidOperationException Operación inválida en estado actual del objeto
InteropException Base de excepciones producidas en comunicación con código inseguro
NullReferenceException Acceso a miembro de objeto que vale null
OverflowException Desbordamiento dentro de contexto donde se ha de comprobar los desbordamientos (expresión constante,
instrucción checked, operación checked u opción del compilador /checked)
OutOfMemoryException Falta de memoria para crear un objeto con new
SEHException Excepción SHE del API Win32
StackOverflowException Desbordamiento de la pila, generalmente debido a un excesivo número de llamadas recurrentes.
TypeInizializationException Ha ocurrido alguna excepción al inicializar los campos estáticos o el constructor estático de un tipo. En
InnerException se indica cuál es.
¿Por qué se emplean excepciones?

 El tradicional tratamiento procedural de errores es


demasiado complicado
Lógica
Lógica del
del programa
programa

int
interrorCodigo
errorCodigo==0;0;
FileInfo
FileInfosource
source==new
newFileInfo("code.cs");
FileInfo("code.cs");
ifif(errorCodigo
(errorCodigo== ==-1)
-1)goto
gotoFallo;
Fallo;
int
intlongitud
longitud==(int)source.Length;
(int)source.Length;
ifif(errorCodigo
(errorCodigo== ==-2)
-2)goto
gotoFallo;
Fallo;
char[]
char[]contenido
contenido==new newchar[longitud];
char[longitud];
ifif(errorCodigo
(errorCodigo== ==-3)
-3)goto
gotoFallo;
Fallo;
////No
Nohay
hayproblemas
problemas......
Fallo:
Fallo:...... Trat.
Trat. De
De errores
errores
Ejemplo
class ExceptionTest
{
static double SafeDivision(double x, double y)
{
if (y == 0)
throw new System.DivideByZeroException();
return x / y;
}
static void Main()
{
// Input for test purposes. Change values
// to see exception handling behavior.
double a = 98, b = 0;
double result = 0;
try
{
result = SafeDivision(a, b);
Console.WriteLine("{0} dividido entre {1} = {2}", a, b, result);
}
catch (DivideByZeroException )
{
Console.WriteLine(“Intentas dividir entre cero.");
}
}
}
Uso de bloques try-catch
 Solución orientada a objetos para el
tratamiento de errores
 Poner el código normal en un bloque try
 Tratar las excepciones en un bloque catch aparte

try Lógica
Lógica del
delprograma
try{{ programa
Console.WriteLine("Escriba
Console.WriteLine("Escribaun unnúmero");
número");
int
intii==int.Parse(Console.ReadLine());
int.Parse(Console.ReadLine()); Tratamiento
Tratamiento de
de errores
errores
}}
catch
catch(OverflowException
(OverflowExceptioncapturada)
capturada)
{{
Console.WriteLine(capturada);
Console.WriteLine(capturada);
}}
Bloques catch múltiples
 Cada bloque catch captura una clase de excepcion
 Un bloque try puede tener un bloque catch general
 Un bloque try no puede capturar una clase derivada de una clase
capturada en un bloque catch anterior
try
try
{{
Console.WriteLine(“Escriba
Console.WriteLine(“Escribaelelprimer
primernúmero");
número");
int
intii==int.Parse(Console.ReadLine());
int.Parse(Console.ReadLine());
Console.WriteLine("Escriba
Console.WriteLine("Escribaelelsegundo
segundonúmero");
número");
int
intjj==int.Parse(Console.ReadLine());
int.Parse(Console.ReadLine());
int
intkk==ii//j;j;
}}
catch
catch(OverflowException
(OverflowExceptioncapturada)
capturada){…}
{…}
catch
catch(DivideByZeroException
(DivideByZeroExceptioncapturada)
capturada){…}
{…}
El siguiente código ayudará a comprender mejor lo que
ocurre en un bloque try-catch múltiple:

try {
Console.WriteLine("Escriba el primer número");
int i = int.Parse(Console.ReadLine());
Console.WriteLine("Escriba el segundo número");
int j = int.Parse(Console.ReadLine());
int k = i / j;
}
catch (OverflowException capturada)
{
Console.WriteLine(capturada);
}
catch(DivideByZeroException capturada)
{
Console.WriteLine(capturada);
}
. ...
La instrucción throw
 Lanza una excepción apropiada
 Asigna a la excepción un mensaje significativo

throw
throwexpression
expression;;

ifif(minuto
(minuto<<11||||minuto
minuto>=>=60)
60){{
throw
thrownewnewInvalidTimeException(minuto
InvalidTimeException(minuto++
""no
noes
esun
unminuto
minutoválido");
válido");
////!!!!No
Noalcanzado
alcanzado!!!!
}}
La cláusula finally
 Las instrucciones de un bloque finally se ejecutan

Monitor.Enter(x);
Monitor.Enter(x);
try
try{{
...... Bloques
Bloques catch
catch opcionales
opcionales
}}
finally
finally{{
Monitor.Exit(x);
Monitor.Exit(x);
}}
Comprobación de desbordamiento aritmético

 Por defecto, el desbordamiento aritmético no se comprueba


 Un comando checked activa la comprobación de desbordamiento

checked
checked{{ OverflowException
OverflowException
int
intnumero
numero==int.MaxValue;
int.MaxValue;
Console.WriteLine(++numero);
Console.WriteLine(++numero); Se lanza un objeto excepción.
}} WriteLine no se ejecuta

unchecked
unchecked{{
int
intnumero
numero==int.MaxValue;
int.MaxValue; MaxValue + 1 es negativo?
Console.WriteLine(++numero);
Console.WriteLine(++numero);
}} -2147483648
Normas para el tratamiento de excepciones

 Lanzamiento
 Evitar excepciones para casos normales o esperados
 Nunca crear ni lanzar objetos de clase Exception
 Incluir una cadena de descripción en un objeto
Exception
 Lanzar objetos de la clase más específica posible

 Captura
 Ordenar los bloques catch de lo específico a lo
general
 No permitir que salgan excepciones de Main
Excepciones
 Una excepción es el indicador de un problema: una mala
operación o situación anómala que ocurre durante la
ejecución de un programa.
 Las excepciones deben ser interceptadas y manejadas para

no desestabilizar el programa.
 Todas las excepciones son instancias de System.Exception

o de sus derivadas.
 El CLR provee un número amplio de excepciones

predefinidas: ArgumentNullException, InvalidCastException,


OverflowException, etc.
 Se pueden crear excepciones personalizadas derivando de

System.Exception.
Manejando las excepciones
 Las excepciones deben ser atrapadas y controladas para asegurar
la continuidad del programa.

 Si la función en ejecución C() no intercepta la excepción, se le da


la oportunidad a la función B() o función solicitante.
 Si B() no intercepta la excepción, se la da la oportunidad a la función
A().
 Si A() no intercepta la excepción, el CLR la intercepta y termina el
programa en forma abrupta.

 Las excepciones se manejan con las sentencias: try - catch -


finally
Sentencias try-catch
 Encerrar cualquier código sospechoso de generar una excepción dentro de un bloque try.
 Atrapar la excepción lanzada dentro del bloque catch.

–Consisten en un bloque try seguida de una o más cláusulas catch.


–No se pueden utilizar variables que han sido declaradas dentro de un bloque try, fuera del mismo.

int SafeDivision(int x, int y)


{
try
{

return (x / y);
}
catch (System.DivideByZeroException dbz)
{
System.Console.WriteLine("Division by zero attempted!");
return 0;
}
}
Clausula catch
Cláusula catch
 La cláusula catch puede ser utilizada sin argumentos, la cual captura cualquier tipo de excepción.

public void Func2( )


{
Console.WriteLine( "Enter Func2..." );
try
{
Console.WriteLine( "Entering try block..." );
throw new ApplicationException( );
// this code never executes because of the exception
Console.WriteLine( "Exiting try block..." );
}
catch
{
Console.WriteLine( "Exception caught and handled!" );
}
Console.WriteLine( "Exit Func2..." );
}
Cláusula catch
 Pueden existir múltiples cláusulas catch, las cuales pueden tomar un argumento de tipo objeto, derivado de
System.Exception.

static void Main()


{
try
{
string s = null;
ProcessString(s);
} // Most specific:
catch (ArgumentNullException e)
{
Console.WriteLine("{0} First exception caught.", e);
}// Least specific:
catch (Exception e)
{
Console.WriteLine("{0} Second exception caught.", e);
}
}
Tipos de catch
Sentencia throw
 Las excepciones se pueden relanzar, para ser recapturadas por el método
solicitante, o capa superior.
 Se puede utilizar el catch sin parámetros para excepciones no-manejadas por el
CLR.
try
{
try // try to access a resource
{ }
// try to access a resource catch (System.UnauthorizedAccessException
} e)
{
catch LogError(e); // call a custom error logging procedure
{ throw e;
throw; // re-throw the error // re-throw the error
//throw;
}
// also works !!
}
Sentencias try-catch-finally
El bloque finally es útil para limpiar y liberar recursos utilizados en el bloque try. Se puede utilizar para cerrar conexiones a BD,
cerrar
archivos, limpiar el buffer, etc.
Se ejecuta después de la ejecución de los bloques try y catch.

El bloque finally siempre se ejecuta, independiente del resultado del bloque try.

public class MainClass


{
static void Main()
{
int i = 123;
string s = "Some string";
object o = s;
try
{

// Invalid conversion; „o‟ contains a string not an int


i = (int)o;
}
finally
{
Console.Write("i = {0}", i);
} } }
Try – catch - finally
Ejemplos Sentencias try-catch-finally
using System;
static void CodeWithCleanup() public class EHClass
{ {
System.IO.FileStream file = null; static void Main()
System.IO.FileInfo fileInfo = null; {
try try
{ {
fileInfo = new System.IO.FileInfo("C:\\file.txt"); Console.WriteLine("Executing the try statement.");
file = fileInfo.OpenWrite(); throw new NullReferenceException();
file.WriteByte(0xF); }
}
catch (NullReferenceException e)
{
catch(System.Exception e)
Console.WriteLine("{0} Caught exception #1.", e);
{
}
System.Console.WriteLine(e.Message);
catch
} {
finally Console.WriteLine("Caught exception #2.");
{ }
if (file != null) finally
{
{
Console.WriteLine("Executing finally block.“);
file.Close();
}
} }
} }
}
La Clase System.Exception
 PropiedadStackTrace (string / read-only)
 Devuelve una cadena con el nombre de los métodos de la
pila.
 Devuelve el número de línea donde se generó la excepción
en cada método.
 PropiedadMessage (string / read-only)
 Devuelve una cadena explicativa de la razón de la excepción.
 PropiedadHelpLink (string / read-only)
 Se puede establecer para devolver un link con información
de ayuda para resolver el problema.
Ejemplos de uso de la clase Exception

public void Run( )


{
try
{
Console.WriteLine( "Open file here" );
double a = 12;
double b = 0;
Console.WriteLine( "{0} / {1} = {2}“, a, b, DoDivide( a, b ) );
Console.WriteLine("This line may or may not print" );

}
// most derived exception type first
catch (DivideByZeroException e )
{
Console.WriteLine(“DivideByZeroException! Msg: {0}“,e.Message );
Console.WriteLine(“HelpLink: {0}", e.HelpLink );
Console.WriteLine(“Here's a stack trace: {0}\n“, e.StackTrace );
}
catch
{
Console.WriteLine("Unknown exception caught" );

}
finally
{
Console.WriteLine("Close file here." );
}
}

También podría gustarte