UNIVERSIDAD DON BOSCO FACULTAD DE ESTUDIOS TECNOLÓGICOS ESCUELA DE COMPUTACION GUIA DE LABORATORIO #08 CICLO: 02/ 2012 Nombre de la Practica: Manejo de Errores (Try Catch) Lugar de Ejecución: Centro de Computo Tiempo Estimado: 2 horas y 30 minutos MATERIA: Lenguajes de Programación 1 I. OBJETIVOS Que el estudiante sea capaz de: • Defina ¿Que son las excepciones en VB.NET? • Controlar las excepciones que se puedan dar en determinados momentos de la ejecución de una aplicación • Elabore manejos de excepciones estructuradas y no estructuradas. II. INTRODUCCION TEORICA Manipulación de errores Cuando se comienza a desarrollar, normalmente el (la) programador(a) se hace el cuestionamiento ¿llegara a escribir códigos que no contengan errores? La experiencia de muchos desarrolladores nos dice que esa es una habilidad muy difícil, por no decir imposible de desarrollar. Es por eso que Visual Studio .Net brinda las herramientas que facilitan la detección y la manipulación de los errores. Las computadoras no son inteligentes. Hacen exactamente lo que se les ordena, por lo que si comete un error y se les indica secuencias de comandos incorrectos, lo harán de todos modo. Un error es algo que no está previsto que ocurra en el programa. Existen muchos tipos de errores que pueden producirse en un programa de computadora como: a) errores de sintaxis b) errores lógicos c) errores de tiempo de ejecución. Errores de Sintaxis Suceden al escribir código en la aplicación; como por ejemplo una instrucción mal escrita, omisión de un parámetro obligatorio en una función, etc. Visual Basic notifica de cualquier error de sintaxis mostrando una marca de subrayado azul (por defecto) con un comentario indicando la causa del error. Este tipo de error puede ser reparado con facilidad con ayuda del editor de codigo de Visual Studio!! 1 Guía # 08: Manejo de Errores (Try Catch) Una ayuda para corregir errores de sintaxis, es usar la sentencia Option Explicit que fuerce a declarar variables y evitar expresiones inválidas. Errores Lógicos Ocurren una vez usada la aplicación y, consiste en resultados inesperados o no deseados; por ejemplo una función que debe devolver el sueldo neto está devolviendo un valor de cero o negativo, o una subrutina que debe eliminar un archivo temporal no lo está borrando. Estos errores son los más difíciles de capturar, ya que el código se encuentra correctamente escrito (sintaxis correcta), y el problema se generar por un fallo de planteamiento en el código. Esto ocasiona por ejemplo: el control del programa no entra en un bucle porque una variable no ha tomado determinado valor; el flujo del programa sale antes de lo previsto de un procedimiento, al evaluar una expresión que esperábamos que tuviera un resultado diferente, etc. Para corregir este tipo de errores se hace uso de las herramientas de depuración, como por ejemplo un seguimiento paso a paso, o inspeccionar el valor de una variable o expresión. También podemos disminuir errores o excepciones de tipos de datos no deseados usando la sentencia Option Strict que evita la conversión forzosa y verifica que el tipo de dato asignado sea del mismo tipo que la variable o función, o que un parámetro pasado sea del mismo tipo, etc. Errores en Tiempo de Ejecución Este tipo de errores suceden en plena ejecución de la aplicación, después de haber sido compilado el código. No son errores de mala escritura ni de lógica, sino más bien de alguna excepción del sistema, como por ejemplo tratar de leer un archivo que no existe o que está abierto, realizar una división entre cero, etc. Para controlar los errores en tiempo de ejecución se dispone de los Manipuladores o Controladores de Error, que evitan la caída del programa y permiten que siga funcionando, como vera mas adelante. Errores y Excepciones Dentro del esquema de gestión de errores del entorno .NET Framework, se identifican al evento Error y al objeto Excepción). Estos elementos son utilizados indistintamente en muchas ocasiones para hacer referencia genérica a la activación de errores; sin embargo, aunque complementarios, cada uno tiene su propia funcionalidad dentro del proceso de tratamiento de un error. • Error. Un error es un evento que se produce durante el funcionamiento de un programa, provocando una interrupción en su flujo de ejecución. Al producirse esta situación, el error genera un objeto excepción. • Excepción. Una excepción es un objeto características del error que se ha producido. generado por un error, que contiene información sobre las Tome en cuenta que una Excepcion en .NET: Se basa en la clase System.Exception Puede superar los límites del proceso y de la máquina Puede tratarse de la misma forma, independientemente del lenguaje de .NET en el que estén escritas o el lenguaje en el que sea procesada la excepción. Controla el procedimiento y la línea de código culpables de un error en la invocación de cadena mediante la propiedad StackTrace. En la Tabla 8.1 se muestra un listado de algunas de las propiedades más habituales de la clase Exception. Lenguajes de Programación 1 2 Guía # 08: Manejo de Errores (Try Catch) Manipuladores de Excepciones Un manipulador de excepción es un bloque de código que proporciona una respuesta al error que se ha producido, y que se incluye en una estructura proporcionada por el lenguaje a tal efecto, es decir, para la captura de excepciones. Propiedad Descripción HelpLink Obtiene o establece la ubicación del archivo de ayuda asociado a la excepción HResult Obtiene o establece el valor HRESULT. Se trata de un valor numérico y codificado asociado a una excepción concreta. InnerException Obtiene una referencia de la excepción interna Message Obtiene o establece la representación en forma de cadena del mensaje de error asociado a la excepción. Source Obtiene o establece el nombre de la aplicación u objeto causante de la excepción. StackTrace Obtiene el rastro de pila que identifica el punto en el que ha surgido la excepción en el código TargetSite Obtiene el método que generó la excepción. Tabla 8.1: Propiedades de la Clase Exception Tipos de tratamiento de error en VB.NET VB.NET proporciona dos tipos de tratamiento de error: Estructurado y No estructurado. El primero se basa en los esquemas de captura de errores de lenguajes como C# y C++; gestionando los errores a través de excepciones, y una estructura de control que se encarga de atrapar aquellas excepciones que se produzcan. El segundo es un sistema heredado de versiones anteriores de VB, y está basado en la detección y captura de errores a través de etiquetas de código, mediante saltos no estructurados en el flujo de la ejecución. A. Manipulación no estructurada de errores En este tipo de gestión de errores, cada vez que se produce un error, se consultará al objeto del sistema Err. Este objeto contiene, a través de sus propiedades, la información sobre el error producido. Para poder capturar los errores mediante este sistema, se utilizará la instrucción On Error, que permitirá seleccionar el controlador de errores a ejecutar. Existen varias sintaxis o formas de usar la sentencia On Error, tal como se define: 1. On Error Resume Next: Indica que si ocurre un error en tiempo de ejecución el flujo continúe en la siguiente línea después de la que originó el error. 2. On Error GoTo 0: Deshabilita cualquier Controlador de error, configurando este a Nothing. previamente declarado en el procedimiento actual, 3. On Error GoTo –1: Deshabilita cualquier error o excepción que ocurra en cualquier línea del procedimiento actual, configurando este a Nothing. Lenguajes de Programación 1 3 Guía # 08: Manejo de Errores (Try Catch) 4. On Error GoTo Etiqueta: Si un error en tiempo de ejecución ocurre envía el control a la instrucción que está debajo de la etiqueta definida. Es la mejor forma no estructurada de controlar errores, ya que se puede personalizar mensajes. Tabla 8.2: Sintaxis general de uso de sentencia On Error Este objeto se crea automáticamente al iniciarse la aplicación, y proporciona al usuario información sobre los errores producidos en el transcurso de la aplicación. Tiene ámbito público, por lo que se puede usar desde cualquier punto del programa. Cuando se produzca un error, la propiedad Number de este objeto tendrá un valor mayor de cero, mientras que la propiedad Description, dará una información textual del error producido. La forma de implementar esta sentencia en un procedimiento es la siguiente: Inicio Procedimiento( ) On Error GoTo <Etiqueta> <Instrucciones> Exit Sub <Etiqueta>: <Instrucciones> [Resume ¦ Resume Next ¦ Resume Etiqueta] Fin Procedimiento Para salir de la etiqueta, generalmente se usa la instrucción Resume de 3 formas: Resume: Vuelve a la instrucción que produjo el error. Resume Next: Regresa el flujo a la siguiente instrucción después de la que produjo el error. Resume Etiqueta: Bifurca el control a una etiqueta definida por el usuario. * Nota: Los ejemplos que se exponen a continuación han sido creados en proyectos de Visual Basic.NET en modo Consola. Ejemplos de evento On Error Observe a continuación un ejemplo de la sintaxis utilizada con On Error GoTo Etiqueta: Public Sub Main() On Error Goto ControlErrores Dim dtFecha As Date Console.WriteLine("Introducir una fecha") dtFecha = Console.ReadLine() Console.WriteLine("Esta línea se ejecuta después del error") Console.ReadLine() Exit Sub ' --- etiqueta de control de errores ---- ControlErrores: Console.WriteLine("Error: {0} - {1}", Err.Number, Err.Description) Console.ReadLine() Resume End Sub Lenguajes de Programación 1 4 Guía # 08: Manejo de Errores (Try Catch) Ahora un ejemplo con On Error Resume Next: Public Sub Main() On Error Resume Next Dim dtFecha As Date Console.WriteLine("Introducir una fecha") dtFecha = Console.ReadLine() If Err.Number > 0 Then Console.WriteLine("Error: {0} - {1}", Err.Number, Err.Description) Console.ReadLine() Err.Clear() End If Console.WriteLine("Esta línea se ejecuta después de un posible error") Console.ReadLine() End Sub Se debe tomar en cuenta que el método Raise( ), del objeto Err, permite generar errores propios del programador, los cuales se comportarán igual que los errores del sistema: Public Sub Main() On Error Goto ControlErrores ‘Cuando se produzca el error saltar al controlador del mismo. Dim iValor As Integer Console.WriteLine("Introducir un número") iValor = Console.ReadLine() If iValor > 500 Then Err.Raise(5100, , "El número debe ser menor de 500") End If Console.WriteLine("Esta línea se ejecuta después de un posible error") Console.ReadLine() Exit Sub ' ---- etiqueta de control de errores ----- ControlErrores: Console.WriteLine("Error: {0} - {1}", Err.Number, Err.Description) Console.ReadLine() Resume Next End Sub Con la instrucción On Error Goto 0, se desactiva el manejador de errores que hubiera activado hasta el momento; de modo, que a no ser que activemos otro manejador, los errores que se produzcan a partir de esa línea, provocarán un error fatal, la cancelando de la ejecución de todo el programa. Observe el siguiente ejemplo: Public Sub Main() On Error Goto ControlErrores Dim iValor As Integer Console.WriteLine("Introducir un número") iValor = Console.ReadLine() On Error Goto 0 Console.WriteLine("Introducir otro número") iValor = Console.ReadLine() Lenguajes de Programación 1 5 Guía # 08: Manejo de Errores (Try Catch) Console.ReadLine() Exit Sub ' --------- etiqueta de control de errores -------- ControlErrores: Console.WriteLine("Error: {0} - {1}", Err.Number, Err.Description) Console.ReadLine() Resume Next End Sub B. Manipulación Estructurada de Errores (sentencia Try). En este tipo de tratamiento, cada vez que se produce un error, se genera un objeto de la clase Exception o alguna de sus derivadas, conteniendo la información del error ocurrido. La manera de capturar este tipo de objetos pasa por utilizar una estructura de control del lenguaje, proporcionada para esta finalidad: Estructura Try…End Try Esta estructura de control del lenguaje, proporciona el medio para definir un bloque de código sensible a errores, y los correspondientes manipuladores de excepciones, en función del tipo de error producido. La forma de implementar esta sentencia en un procedimiento es: Inicio Procedimiento() Try <Instrucciones Try> [Exit Try] [Catch 1 [<Excepcion> [As <Tipo Dato>]] <Instrucciones Catch 1> [Exit Try] [When <Expresión>]] [Catch 2 [When <Expresión>]] [<Excepción> [As <Tipo Dato>]] <Instrucciones Catch 2> [Exit Try] : [Catch n [<Excepción> [As <Tipo Dato>]] [When <Expresión>]] <Instrucciones Catch n> [Exit Try] Finally <Instrucciones Finally> End Try Fin Procedimiento Las partes de la sintaxis de esta estructura Try-Catch son las siguiente: 1. En primer lugar se encuentra la declaración mediante la palabra clave Try. Todo el código que se escriba a partir de dicha palabra clave, y hasta la primera sentencia Catch, es el código que se define como sensible a errores, o dicho de otro modo, el bloque de instrucciones sobre las que se desea que se active el control de errores cuando se produzca algún fallo en su ejecución. 2. A continuación, se establece cada uno de los manipuladores de excepción mediante la palabra clave Catch. Junto a esta palabra clave, se situara de forma opcional, un identificador que contendrá el objeto con la excepción generada. Finalmente, y también de modo opcional, con la palabra clave When, se especifica una condición para la captura del objeto de excepción. Se puede escribir uno o varios manipuladores Catch dentro de una estructura de control Try...End Try. 3. Cada vez que se produzca un error, el flujo de la ejecución saltará a la sentencia Catch más acorde con el tipo de excepción generada por el error, siempre y cuando hayamos situado varios manipuladores de excepciones en el controlador de errores. Lenguajes de Programación 1 6 Guía # 08: Manejo de Errores (Try Catch) Cuando no se establece el tipo de error producido, se está trabajando de la forma más genérica posible, observe el siguiente ejemplo: Public Sub Main() Dim sValor As String, iNumero As Integer Try 'comienza el control de errores Console.WriteLine("Introducir un número") sValor = Console.ReadLine() 'Hasta se ejecuta si no se ha introducido un número... iNumero = sValor ' ...aquí se producirá un error y no se ejecutar la linea siguiente del código normal iNumero = iNumero + 1000 Catch ' si se produce un error, se genera una excepción que capturamos en este bloque de código ' manipulador de excepción, definido por Catch Console.WriteLine("Error al introducir el número" & _ControlChars.CrLf & _"El valor {0} es incorrecto", _sValor) End Try ' resto del código del procedimiento Console.ReadLine() End Sub 4. Tanto si se produce un error o no, la sentencia Finally de la estructura Try...End Try, permite escribir un bloque de código que será ejecutado al darse una condición de error, o bajo una ejecución normal del procedimiento. Esta sentencia se ejecuta ya sea que ocurra un error ó que no. Ver el ejemplo anterior con la sentencia Finally incorporada: Public Sub Main() Dim sValor As String, iNumero As Integer Try ' comienza el control de errores Console.WriteLine("Introducir un número") sValor = Console.ReadLine() ' si no hemos introducido un número... iNumero = sValor ' ...aquí se producirá un error... ' ...y no llegaremos a esta parte del código iNumero = iNumero + 1000 Catch ' si se produce un error, se genera una excepción que capturamos en este bloque de código ' manipulador de excepción, definido por Catch Console.WriteLine("Error al introducir el número" & _ControlChars.CrLf & _"Valor {0} es incorrecto", _sValor) Finally 'si se produce un error, después de Catch se ejecuta este bloque; 'si no se produce error, después de Try también se ejecuta Console.WriteLine("El controlador de errores ha finalizado") End Try ' resto del código del procedimiento Lenguajes de Programación 1 7 Guía # 08: Manejo de Errores (Try Catch) Dim dtFecha As Date Console.WriteLine("Introducir una fecha") ' si ahora se produce un error, al no disponer de una estructura para controlarlo ' se cancelará la ejecución dtFecha = Console.ReadLine() Console.WriteLine("La fecha es {0}", dtFecha) Console.ReadLine() End Sub La clase EXCEPTION Como se ha mencionado antes, cada vez que se produce un error, el entorno de ejecución genera una excepción con la información del error generado. Para facilitar la tarea de manipulación de la excepción producida, en un controlador de excepciones se obtiene un objeto de la clase Exception, o de alguna de sus derivadas, de forma que, a través de sus miembros, podemos saber qué ha pasado. Entre las propiedades y métodos que podemos utilizar, se encuentran las siguientes: • Message. Descripción del error. • Source. Nombre del objeto o aplicación que provocó el error. • StackTrace Ruta o traza del código en la que se produjo el error. • ToString( ) La cadena devuelta contiene información detallada del error. En esta cadena se puede encontrar también, los valores obtenidos de las propiedades anteriores; por lo que el uso de este método, en muchas ocasiones será el modo más recomendable para obtener los datos claves de la excepción. Para obtener el objeto de excepción creado a partir del error, se utiliza la sentencia Catch de la estructura Try. Para ello, a continuación de Catch, se escribe el nombre de un identificador, definiéndolo como tipo Exception o alguno de los tipos de su jerarquía. Tomando como base el código anterior se ubica a la clase de la siguiente manera: ' .... Try ' .... Catch oExcep As Exception ' si se produce un error, se crea un objeto excepción que capturamos volcándolo a un identificador ' de tipo Exception Console.WriteLine("Se produjo un error. Información de la excepción") Console.WriteLine("Message: {0}", oExcep.Message) Console.WriteLine("Source: {0}", oExcep.Source) Console.WriteLine() Console.WriteLine("StackTrace: {0}", oExcep.StackTrace) Console.WriteLine() Console.WriteLine(oExcep.ToString()) Message: Cast from String ('hola') to Integer is not valid. Source: Microsoft.VisualBasic StackTrace: at Microsoft.VisualBasic.Helpers.IntegerType.FromString(String Value)at K:\CursoVBNET\Texto\t16Errores\ErroresPru\Module1.vb:line 12 Finally ' .... End Try ' .... Lenguajes de Programación 1 8 ErroresPru.Module1.Main() in Guía # 08: Manejo de Errores (Try Catch) Exception representa la clase base en la jerarquía de tipos de excepción que se pueden producir dentro del entorno de ejecución. Partiendo de Exception, disponemos de un conjunto de clases derivadas, que nos permiten un tratamiento más particular del error producido, como ApplicationException, IOException, SystemException, etc. Cada una de ellas puede tener, además de los miembros generales de Exception, una serie de métodos y propiedades particulares de su tipo de excepción; por ello, lo más conveniente, será utilizar estas clases, a través de las que podremos averiguar más detalles sobre el problema producido. A continuación se muestra un ejemplo en que se realizan capturas de diferentes tipos de errores en el mismo controlador: Public Sub Main() Dim sValor As String, iNumero As Integer Dim sLetras() As String = {"a", "b", "c", "d"} Try ' comienza el control de errores Console.WriteLine("Introducir un número") sValor = Console.ReadLine() ' si no hemos introducido un número... iNumero = sValor ' ...aquí se producirá un error... ' ...y no llegaremos a esta parte del código iNumero = iNumero + 1000 ' introducir una letra y asignarla a una posición del array Dim sNuevaLetra As String, iPosicion As Integer Console.WriteLine("Introducir una letra") sNuevaLetra = Console.ReadLine() Console.WriteLine("Introducir posición del array para la letra") iPosicion = Console.ReadLine() ' si al asignar la letra al array no existe el índice, se producirá un error sLetras(iPosicion) = sNuevaLetra Catch oExcep As System.InvalidCastException ' excepción producida por un error al intentar realizar una conversión de tipos Console.WriteLine(oExcep.ToString()) Catch oExcep As System.IndexOutOfRangeException ' excepción producida por un error al intentar usar un índice inexistente de array, o índice fuera de rango Console.WriteLine(oExcep.ToString()) Finally ' si se produce un error, después de Catch se ejecuta este bloque; ' si no se produce error, después de Try también se ejecuta Console.WriteLine("El controlador de errores ha finalizado") End Try Console.ReadLine() End Sub Estableciendo una condición para un manipulador de excepciones Mediante la cláusula When, de la sentencia Catch, se puede situar una expresión que sirva como filtro o condición, para que dicho manipulador de excepciones se ejecute, en función de que el resultado de la expresión devuelva True o False. Lo expresado anteriormente, se pone en evidencia en el siguiente ejemplo: Lenguajes de Programación 1 9 Guía # 08: Manejo de Errores (Try Catch) Public Sub Main() Dim byMiNum As Byte, dtFHActual As Date dtFHActual = System.DateTime.Today() ' obtener la fecha actual Try ' comienza el control de errores Console.WriteLine("Introducir un número") ' si introducimos un número no incluido en el rango de Byte... byMiNum = Console.ReadLine() Catch oExcep As OverflowException When (dtFHActual.Month = 3) ' ...saltará este manipulador de excepciones, pero sólo cuando las excepciones de desbordamiento ' se produzcan en el mes de Marzo Console.WriteLine("El número introducido " & _ "no se encuentra en el rango adecuado") Finally Console.WriteLine("El controlador de errores ha finalizado") End Try Console.ReadLine() End Sub Si queremos capturar también el resto de excepciones de desbordamiento, u otro tipo de excepciones, tenemos varias alternativas que describimos seguidamente. • Quitar la condición de filtro al manipulador de excepciones actual. De este modo, capturaremos todas las excepciones de desbordamiento, pero no podremos filtrar por un mes determinado. • Añadir un nuevo manipulador a la estructura de control, para todas las excepciones de desbordamiento. En esta situación, si se produce un error de desbordamiento, y no estamos en el mes definido por el anterior manipulador, se ejecutará este nuevo manipulador. • Añadir un manipulador de excepciones genérico. Con esto evitaremos el mensaje de error no controlado, generado por el IDE. Si por ejemplo, además de las operaciones con el tipo Byte, nos encontramos manipulando fechas, podremos capturar todas las excepciones producidas. Public Sub Main() Dim byMiNum As Byte Dim dtFecha As Date, dtFHActual As Date dtFHActual = System.DateTime.Today()' obtener la fecha actual Try ' comienza el control de errores Console.WriteLine("Introducir un número") ' si introducimos un número no incluido en el rango de Byte, según el mes actual iremos ' a uno de los manipuladores de excepción existentes byMiNum = Console.ReadLine() ' si introducimos un valor incorrecto para la fecha, iremos al controlador de errores genérico Console.WriteLine("Introducir una fecha") dtFecha = Console.ReadLine() Catch oExcep As OverflowException When (dtFHActual.Month = 3) ' manipulador de excepciones sólo cuando las excepciones de desbordamiento ' se produzcan en el mes de Marzo Console.WriteLine("El número introducido " & _"no se encuentra en el rango adecuado") Catch oExcep As Exception Lenguajes de Programación 1 10 Guía # 08: Manejo de Errores (Try Catch) ' manipulador genérico de excepciones Console.WriteLine("Se ha producido un error") Catch oExcep As Exception ' manipulador genérico de excepciones Dim oTipo As Type oTipo = oExcep.GetType() Console.WriteLine("Se ha producido un error de tipo {0}", oTipo.Name) Finally Console.WriteLine("El controlador de errores ha finalizado") End Try Console.ReadLine() End Sub El orden en los que se situe a las sentencias Catch dentro de una estructura Try...End Try, es determinante, a la hora de que ciertas excepciones puedan o no, ser capturadas. Por este motivo, al escribir un controlador de errores, se recomienda situar en primer lugar, los manipuladores más específicos, y dejar para el final, los más genéricos. A continuación un ejemplo de esta sugerencia: Public Sub Main() Dim byMiNum As Byte, aValores() As String = {"a", "b", "c"} Try ' comienza el control de errores Console.WriteLine("Introducir un número") ' si no es un número Byte se produce error byMiNum = Console.ReadLine() aValores(5) = "d" ' esta línea produce error siempre, ya que en el array no existe el índice/posicion 5 Catch oExcep As Exception ' manipulador genérico de excepciones, captura todo tipo de excepciones, por lo que si también ' se produce una excepción OverflowException, se ejecutará este manipulador, por estar situado primero Console.WriteLine("Se ha producido un error") Catch oExcep As OverflowException ' captura de errores de desbordamiento, este manipulador nunca se ejecutará, por estar ' uno más genérico antes Console.WriteLine("El número introducido no se encuentra en el rango adecuado") Finally Console.WriteLine("El controlador de errores ha finalizado") End Try Console.ReadLine() End Sub Mediante la sentencia Exit Try, se obliga al programa a salir de la estructura de control de errores, desde cualquier punto en que se ejecute. ' .... Try ' comienza el control de errores Console.WriteLine("Introducir un número") byMiNum = Console.ReadLine() ' si no es un número Byte se produce error Exit Try ' salimos de controlador de errores sin finalizarlo aValores(5) = "d" ' esta línea produce error siempre, ya que no existe el índice 5 en el array Lenguajes de Programación 1 11 Guía # 08: Manejo de Errores (Try Catch) Catch oExcep As OverflowException ' .... Catch oExcep As Exception ' .... ' .... End Try Creación de excepciones personalizadas En algunos escenarios de trabajo, puede suceder que la información proporcionada por alguno de los objetos Exception no se ajuste a lo que realmente se necesita. Es por tanto, es hora de crear una clase, que herede de la clase base Exception y asi contenga la información a su medida. Tal como se definió en el código anterior, considere que se escribe la clase CtaCredito, para llevar el control de cuentas bancarias. En ella se introducirá el nombre del titular de la cuenta y un importe para el crédito que se desee asignar. No obstante dicho crédito no podrá sobrepasar el valor de 2500, así que; para controlar tal circunstancia, se crea adicionalmente, la clase CreditoExcepction, que heredando de Exception, contendrá información en uno de sus miembros, sobre la excepción producida en cuanto al importe que se intentó asignar a la cuenta. ' clase que contiene información sobre una cuenta bancaria Public Class CtaCredito Private msTitular As String Private mdbDisponible As Double Public Property Titular() As String Get Return msTitular End Get Set(ByVal Value As String) msTitular = Value End Set End Property Public ReadOnly Property Credito() As Double Get Return mdbDisponible End Get End Property ' en este método, si se intenta asignar un importe superior al permitido, se lanza una excepción, ' utilizando un objeto de la clase CreditoException, heredado de Exception Public Sub AsignarCredito(ByVal ldbCredito As Double) If ldbCredito > 2500 Then Throw New CreditoException("Límite disponible: 2500 " & "- Se intentó asignar " & CType(ldbCredito, String)) Else mdbDisponible = ldbCredito End If End Sub End Class ' Esta clase contiene la información sobre un error producido en un objeto CtaCredito Lenguajes de Programación 1 12 Guía # 08: Manejo de Errores (Try Catch) Public Class CreditoException Inherits Exception Private msDescripcion As String Public Sub New(ByVal lsDescripcion As String) ‘constructor objeto CreditoException msDescripcion = lsDescripcion End Sub Public ReadOnly Property Descripcion() As String Get Return msDescripcion End Get End Property End Class El esquema del proceso es el siguiente: cuando al método AsignarCredito( ), de un objeto CtaCredito, se intente asignar un valor no permitido, se genera un nuevo objeto CreditoException y se lanza a través de la palabra clave Throw, que es la encargada de emitir las excepciones en el entorno de ejecución. Desde código cliente, el uso de estas clases sería el siguiente: Module Module1 Public Sub Main() Dim oCredito As New CtaCredito()' crear un objeto de la nueva clase Try ' asignar valores a propiedades oCredito.Titular = "Jaime Peral" oCredito.AsignarCredito(1000) ' esto no produce error Console.WriteLine("El credito actual de {0} es {1:C}", _ oCredito.Titular, oCredito.Credito) oCredito.AsignarCredito(5000) ' esta instrucción sí produce error Catch oExcep As CreditoException ' manipulador para las excepciones producidas sobre un objeto CtaCredito Console.WriteLine("Error al asignar crédito: {0}", oExcep.Descripcion) Finally Console.WriteLine("El controlador de errores ha finalizado") End Try Console.ReadLine() End Sub End Module Opciones de control de excepciones. Para controlar excepciones no solo basta usar una forma de control, sea no estructurada o estructurada, sino también es necesario configurar las opciones de control de excepciones para lo cual del menú “Depurar” y luego “Excepciones”. Aparecerá la ventana de control de excepciones (ver Figura 8.1). Existen 2 momentos en que se pueden controlar las excepciones que son: a. When the exception is thrown: Es cuando la excepción ocurre y se aconseja configurarlo en “Continue”. b. If the exception is not handled: Ocurre cuando la excepción no es controlada, es decir cuando no existe controlador de error, es aconsejable que esté en “Break into the debugger”. Lenguajes de Programación 1 13 Guía # 08: Manejo de Errores (Try Catch) Figura 8.1: Ventana de control de Excepcion de Visual Basic .NET Ambos momentos tienen 3 opciones o formas de control, que son: Break into the debugger: Para y muestra el depurador con la línea donde ocurrió el error en tiempo de ejecución. Continue: Continua la ejecución del programa. Si no existe programa Use parent setting: Indica que se va a usar la configuración de la opción de nivel superior o padre controlador Finaliza la ejecución del III. MATERIALES Y EQUIPO Para la realización de la guía de práctica se requerirá lo siguiente: No. 1 Requerimiento Cantidad Guía de Laboratorio #08 de LP1 1 PC con Microsoft Visual Studio 2010 .NET instalado 1 2 Memoria USB 1 3 Computadora con acceso a Internet 1 IV. PROCEDIMIENTO Para esta práctica deberá crear una carpeta con el nombre de Practica8LP1, en la cual va a guardar todos los archivos de esta práctica y de análisis de resultados. EJEMPLO 1: manejo básico de excepciones 1. En el formulario inicial (Form1), proceda a elaborar el diseño de controles (y sus propiedades) mostrados en la Imagen 8.1 Lenguajes de Programación 1 14 Guía # 08: Manejo de Errores (Try Catch) Diseño Formulario Controles (propiedades a modificar) Control (Name) Name Form1 Text Demostración excepciones Button1 btnSobrecarga Sobrecarga Button2 btnDivision0 Division por cero Button3 btnIndice Indice fuera rango Button4 btnConversion Conversión de Tipo Button5 btnSalir Salir Imagen 8.1: Diseño de formulario del Ejemplo 1 2. Ingrese al editor de codigo y digite el siguiente codigo justo después de iniciar la declaracion de la clase frmEjemplo1 'Arreglo de solo 3 elementos, en posiciones (0, 1 y 2) Private miarreglo() As Integer = {56, -2, 87} Sub CorrerExcepcion(ByVal errorType As Integer) 'Demuestra la generacion de errores y su captura con Tty Catch Dim i1, i2, i3 As Integer Dim d1, d2, d3 As Decimal Dim valorcadena As String = "" Dim numero As Integer = 2 Try 'inicia deteccion de errores de ejecucion Select Case errorType 'genera 4 tipos diferentes de error a proposito Case 0 ' Error: raise overflow exception i1 = 999999999 i2 = 999999999 i3 = i1 * i2 'sobrepasa valor tipo Integer Case 1 ' raise a divide by zero exception d1 = 34 d2 = 0 d3 = d1 / d2 'division imposible Case 2 ' raise index out of range exception 'este indice-arreglo no existe MessageBox.Show(miarreglo(3)) Case 3 ' raise invalid cast exception If (valorcadena <> numero) Then MessageBox.Show("No igual") Lenguajes de Programación 1 15 Guía # 08: Manejo de Errores (Try Catch) End If End Select 'Prepara captura de error (con Cath) y su respectiva respuesta ante los mismos 'PRUEBA DETECCION DESDE EXCEPCIONES ESPECIFICAS... Catch ex As OverflowException MessageBox.Show(ex.Message) 'muestra descripcion del error desencadenado!! Catch ex As DivideByZeroException MessageBox.Show(ex.Message) Catch ex As IndexOutOfRangeException MessageBox.Show(ex.Message) Catch ex As InvalidCastException MessageBox.Show(ex.Message) '... HASTA UNA EXCEPCION GENERAL Catch ex As Exception MessageBox.Show(ex.Message) End Try 'Finaliza deteccion de errores 'Desde aca, cualquier activacion de error, abortaria la aplicacion MsgBox("Alcanzo final de la subrutina CorrerExcepcion") End Sub 3. Ahora ingrese al evento Click del boton btnSobreCarga CorrerExcepcion(0) 'demuestra 1er forma de excepcion 4. Repita el paso anterior para cada boton restante, pero invocando en eventos clic respectivos a la subrutina CorrerExcepcion( ) con argumento 1 (para btnDivision), 2 (btnIndice) y 3 (btnConversion). 5. Agregue el codigo necesario en btnSalir para que finalice la ejecución de la aplicación. 6. Compile y ejecute la aplicación. 7. Presione cada boton y vera que en cada uno se genera una excepcion diferente, pero gracias a Try Catch, se captura el error y se responde apropiadamente al mismo. 8. Guardar los cambios y agregar un nuevo formulario (Form2) a su aplicación VB Lenguajes de Programación 1 16 Guía # 08: Manejo de Errores (Try Catch) Ejemplo 2: Manejo de Excepciones II 1. En el formulario inicial (Form1), proceda a elaborar el diseño de controles (y sus propiedades) mostrados en la Imagen 8.2 Diseño Formulario Controles (propiedades a modificar) Control Name (Name) Form1 Demostración excepciones Button1 btCalcular Calcular Button2 btSalir Salir TextBox1 TextDividendo TextBox2 TextDivisor Textbox3 TextResultado Imagen 8.2: Diseño de formulario del Ejemplo 2 2. Agregue una clase al proyecto con el nombre de MiExcepcion Public Class MiExcepcion Inherits System.Exception Sub New() End Sub 'aplicando conceptos de polimorfismo... Public Overrides Function ToString() As String Return "Error:'Division entre cero no es posible'" End Function End Class 3. Agregue la siguiente porción de código al botón btCalcular Dim x, y As Double Dim r As Double = 0 Try x = Double.Parse(Me.TextDividendo.Text) y = Double.Parse(Me.TextDivisor.Text) Catch ex As Exception MsgBox("Ingrese números") Me.TextDividendo.Clear() Me.TextDivisor.Clear() Me.TextResultado.Text = "Operación sin éxito" Lenguajes de Programación 1 17 Text Guía # 08: Manejo de Errores (Try Catch) Return End Try Try r = divide(x, y) Catch ex As MiExcepcion 'capturamos la excepción que habíamos lanzado. Me.TextResultado.Text = ex.ToString() r = -1 End Try If (r <> -1) Then Dim z As Double = CType(x / y, Double) Me.TextResultado.Text = z End If 4. Cree un función con el nombre divide dentro del Formulario Public Function divide(ByVal x As Integer, ByVal y As Integer) As Integer Dim z As Integer Try z = x / y Return z Catch ex As System.ArithmeticException z = -1 Throw New MiExcepcion 'lanzamos la excepción. Return z End Try End Function 5. Programe el botón Salir 6. Verifique el lanzamiento de una excepción ingresando valores erróneos 7. Responda en que caso funciona la excepción: _____________________________________________________________________________________________ ____________________________________________________________________________________ EJEMPLO 3: tratamiento estructurado de errores 8. En este ejercicio se implementarán el tratamiento estructurado de errores, con el objetivo de poder responder a diferentes situaciones de error que usuario activa al ingresar datos incorrectos a los controles de un form de nuestra aplicación. 9. Desarrolle el diseño mostrado en la Imagen 8.3 en el segundo formulario (Form2) del proyecto. Lenguajes de Programación 1 18 Guía # 08: Manejo de Errores (Try Catch) Control (Name) Text Form2 Manejo de Excepciones personalizas Groupbox1 Interes que aplicara a préstamo Label1, Label2, Label3 “Monto inicial”, “Monto final”, “Tasa interés (%)”, respectivamente Button1 btnAceptar Hacer cálculos TextBox1 y TextBox2 txtP y txtS “0” en cada uno NumericUpDown1 nudInteres RadioButton1 y RadioButton2 “Mensual”, “Trimestral”, respectivamente Imagen 8.3: Diseño de formulario del Ejemplo 3 y modificación de propiedades de sus controles Extra: + Realice los ajustes necesarios para que control nudInteres acepte valores entre (2-40) de %, y con 2 decimales + Ajustar propiedad Checked a True para RadioButton1 10. Ingrese al código del Form2 y digite el código siguiente 'Programa para determinar el tiempo (n años) que un capital base (P) 'se convierte a un monto final (S), 'aplicando un interes I (trimestral o anual) compuesto 'variables generales del Form2 Dim P, S As Decimal 'monto inicial y final Dim tasaI As Decimal 'tasa interes nominal Dim m As Decimal = 12 'tipo capitalizacion (12:mensual o 4: trimestral) 'tiempo N años que requiere saber usuario Dim tiempoN As Decimal Public Sub CalcularN() Dim numerador, denominador As Decimal Lenguajes de Programación 1 19 Guía # 08: Manejo de Errores (Try Catch) Try 'captura datos de cajas texto S = txtS.Text P = txtP.Text If P > S Then Throw New Exception() 'genera una exception propia End If 'recibe tasa interes (I) tasaI = nudInteres.Value 'Hace calculo del tiempo (años) solicitado tasaI /= 100 numerador = Math.Log(S / P) denominador = m * Math.Log(1 + tasaI / m) tiempoN = numerador / denominador MsgBox("Se requieren " & Math.Round(tiempoN, 2) & " años para lograr el monto final ingresado") Catch ex As InvalidCastException MsgBox("tiene errores en digitacion de montos") txtP.Text = "" txtS.Text = "" txtP.Focus() Catch ex2 As DivideByZeroException MsgBox("El monto final no puede ser cero") txtS.Text = "" txtS.Focus() Catch ex3 As Exception MsgBox("El monto inicial debe ser menor que monto final") txtP.Text = "0" txtS.Text = "0" End Try End Sub 11. De igual forma, ingrese al evento Clic del btnAceptar e invoque a la subrutina CalcularN 12. Luego, ingrese al evento CheckedChanged de cada Radiobutton y digite en cada uno: m=12 y m=4, respectivamente. 13. Ejecute el programa y luego realice estas diferentes pruebas, sin detener la ejecución entre medio de ninguna de ellas. • Presione botón “Hacer calculos”, sin haber ingresado dato alguno en cajas de texto • Ingrese texto en ambas cajas e intente calcular el tiempo de préstamo • Digite una cantidad de monto inicial mayor a la del monto final Lenguajes de Programación 1 20 Guía # 08: Manejo de Errores (Try Catch) 14. En todos los casos se generaran excepciones controladas por la estructura Try Catch V. DISCUSION DE RESULTADOS Elabore un documento con el resultado de la siguiente investigación: 1. Investigue al menos diez tipos de problemas que pueden ser tratados con los manejadores de errores en Visual Basic.Net 2010. 2. Investigue al menos veinte números de errores con su respectiva descripción (Errores catalogados por números, según el sistema). 3. ¿Qué son los “hilos” /“thead” dentro de Visual Basic ?, ¿Cómo puede funcionar un hilo y una Excepcion dentro de una aplicacion? VII. BIBLIOGRAFÍA • Bill Evjen, Jason Beres y otros (2002), El libro de Visual Basic.NET (1era Ed), España. Editorial Anaya • Ceballos, Francisco Javier (2006), ENCICLOPEDIA DE MICROSOFT VISUAL BASIC (1er Ed), Mexico, Editorial ALFAOMEGA, ISBN: 9701512189 Lenguajes de Programación 1 21