Sei sulla pagina 1di 31

EXCEPCIONES

Unidad 5
Excepciones
◻ En el lenguaje C#, los errores del programa se difunden en tiempo de
ejecución a través del programa mediante un mecanismo denominado
excepciones. Las excepciones se producen cuando el código encuentra
un error y se detectan mediante el código que puede corregir el error. Las
excepciones se pueden producir mediante el Common Language Runtime
(CLR) de .NET Framework o mediante código de un programa. Una vez que
se produce una excepción, ésta se difunde a la pila de llamadas hasta que
se encuentra una instrucción catch para la excepción. Las excepciones no
detectadas se identifican a través de un controlador de excepciones
genérico proporcionado por el sistema que muestra un cuadro de diálogo.

◻ Las clases derivadas de Exception representan estas excepciones. Esta


clase identifica el tipo de excepción y contiene las propiedades que
albergan detalles acerca de ésta. Producir una excepción implica crear
una instancia de una clase derivada de la excepción, configurar
opcionalmente las propiedades de la excepción y, a continuación, iniciar el
objeto con la palabra clave throw.
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 tener 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 del
programa

int errorCodigo = 0;
FileInfo source = new FileInfo("code.cs");
if (errorCodigo == -1) goto Fallo;
int longitud = (int)source.Length;
if (errorCodigo == -2) goto Fallo;
char[] contenido = new char[longitud];
if (errorCodigo == -3) goto Fallo;
// No hay problemas ...
Fallo: ... Trat. De
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.");
}
}
}
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
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
Lógica del
try { programa
Console.WriteLine("Escriba un número");
int i = int.Parse(Console.ReadLine()); Tratamiento de
} errores
catch (OverflowException capturada)
{
Console.WriteLine(capturada);
}
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;
}
}
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
{
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) {…}
catch (DivideByZeroException capturada) {…}
Clausula catch
Tipos de 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);
}
}
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 cláusula finally
◻ Las instrucciones de un bloque finally se
ejecutan

Monitor.Enter(x);
try {
... Bloques catch opcionales
}
finally {
Monitor.Exit(x);
}
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 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.");
throw new NullReferenceException();
file = fileInfo.OpenWrite();
}
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
{
{
file.Close(); Console.WriteLine("Executing finally block.“);
}
}
}
}
}
}
Instrucción throw
◻ Lanza una excepción apropiada
◻ Asigna a la excepción un mensaje significativo

throw expression ;

if (minuto < 1 || minuto >= 60)


{
throw new InvalidTimeException(minuto + " no es un minuto
válido");
}
Instrucción 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; // re-throw the error
//throw; // also works !!
throw; // re-throw the error }
}
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 { OverflowException
int numero = int.MaxValue;
Console.WriteLine(++numero); Se lanza un objeto excepción.
} WriteLine no se ejecuta

unchecked {
int numero = int.MaxValue; MaxValue + 1 es negativo?
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
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." );
}
}

Potrebbero piacerti anche