Continuamos con la introducción al lenguaje Pascal Moderno.

Esta entrada es una traducción al español, del texto original escrito por Michalis Kamburelis.

Continuamos con la introducción al lenguaje Pascal Moderno.

Esta entrada es una traducción al español, del texto original escrito por Michalis Kamburelis.

Excepciones

Descripción general

Las excepciones permiten interrumpir la ejecución normal del código.

  • En cualquier punto dentro del programa, puede generar una excepción utilizando la palabra clave raise.En efecto, las líneas de código que siguen a la llamada aumentar… no se ejecutarán
  • Se puede capturar una excepción usando una construcción try…except…end. Detectar una excepción significa que de alguna manera «lidias» con la excepción, y el siguiente código debería ejecutarse como de costumbre, la excepción ya no se propaga hacia arriba.
    • Nota: Si se genera una excepción pero nunca se detecta, hará que toda la aplicación se detenga con un error. Pero en las aplicaciones LCL, las excepciones siempre se detectan alrededor de los eventos (y provocan el cuadro de diálogo LCL) si no las detecta antes.
    • En las aplicaciones de Castle Game Engine que usan CastleWindow, de manera similar, siempre detectamos excepciones en torno a sus eventos (y mostramos el cuadro de diálogo adecuado).
    • Por lo tanto, no es tan fácil hacer una excepción que no se detecte en ninguna parte (no se detecte en su código, código LCL, código CGE…).
  • Si bien una excepción interrumpe la ejecución, puede usar la construcción try…finally…end para ejecutar algún código siempre, incluso si el código fue interrumpido por una excepción.
  • La construcción try…finally…end también funciona cuando el código es interrumpido por las palabras clave Break, Continue o Exit. El punto es ejecutar siempre el código en la sección finalmente.

Una «excepción» es, en general, cualquier instancia de clase.

  • El compilador no impone ninguna clase en particular. Solo debe llamar a raise XXX donde XXX es una instancia de cualquier clase. Cualquier clase (por lo tanto, cualquier cosa que descienda de TObject) está bien.
  • Es una convención estándar que las clases de excepción desciendan de una clase de excepción especial. La clase Exception extiende TObject, agregando una propiedad Message de cadena y un constructor para configurar fácilmente esta propiedad. Todas las excepciones generadas por la biblioteca estándar descienden de Exception. Recomendamos seguir esta convención.
  • Las clases de excepción (por convención) tienen nombres que comienzan con E, no con T. Como ESomethingBadHappened.
  • El compilador liberará automáticamente el objeto de excepción cuando se maneje. No lo liberes tú mismo.
  • En la mayoría de los casos, simplemente construyes el objeto al mismo tiempo que llamas a raise, como raise EAlgo MalOcurrido.Crear(‘Descripción de lo malo que sucedió’).

Levantamiento, elevación, propagación (Raising)

Si desea generar su propia excepción, declararla y llame a la elevación… cuando corresponda:

Tenga en cuenta que la expresión que sigue al aumento debe ser una instancia de clase válida para aumentar. Casi siempre creará la instancia de excepción aquí.

También puede usar el constructor CreateFmt, que es un atajo cómodo para Create(Format(MessageFormat, MessageArguments)). Esta es una forma común de proporcionar más información al mensaje de excepción. Podemos mejorar el ejemplo anterior así:

Atrapando

Puede detectar una excepción como esta:

Para mejorar el ejemplo anterior, podemos declarar el nombre de la instancia de excepción (usaremos E en el ejemplo). De esta manera podemos imprimir el mensaje de excepción:

O también podemos comprobar clases de excepciones

También puede reaccionar a cualquier excepción generada, si no usa ninguna expresión:

En general, solo debe capturar excepciones de una clase específica, que señalan un problema particular con el que sabe qué hacer. Tenga cuidado con la captura de excepciones de tipo general (como la captura de cualquier excepción o cualquier TObject), ya que puede capturar fácilmente demasiadas y luego causar problemas al depurar otros problemas.

  • ¿La excepción indica un problema en la entrada del usuario?
  • Entonces deberías reportarlo al usuario.
  • ¿La excepción indica un error en su código? Luego, debe corregir el código para evitar que ocurra la excepción.

Otra forma de capturar todas las excepciones es usar:

Aunque normalmente es suficiente para capturar Exception:

Puede «volver a generar» la excepción en el bloque excepto… final, si así lo decide. Puede hacer aumentar E si la instancia de excepción es E, también puede usar aumentar sin parámetros. Por ejemplo:

Tenga en cuenta que, aunque la excepción es una instancia de un objeto, nunca debe liberarlo manualmente después de generarlo. El compilador generará el código adecuado que se asegura de liberar el objeto de excepción una vez que se maneja.

Finalmente (hacer cosas sin importar si ocurrió una excepción)

A menudo usas try .. La forma de escribirlo se ve así:

Esto siempre funciona de manera confiable y no provoca pérdidas de memoria, incluso si MyInstance.DoSomething o MyInstance.DoSomethingElse generan una excepción.

Tenga en cuenta que esto tiene en cuenta que las variables locales, como MyInstance arriba, tienen valores indefinidos (pueden contener «basura de memoria» aleatoria) antes de la primera asignación. Es decir, escribir algo como esto no sería válido:

El ejemplo anterior no es válido: si ocurre una excepción dentro de TMyClass.Create (un constructor también puede generar una excepción), o dentro de CallSomeOtherProcedure, entonces la variable MyInstance no se inicializa. Llamar a FreeAndNil(MyInstance) intentará llamar al destructor de MyInstance, que probablemente se bloquee con una infracción de acceso (falla de segmentación). En efecto, una excepción provoca otra excepción, lo que hará que el informe de errores no sea muy útil: no verá el mensaje de la excepción original.

A veces se justifica arreglar el código anterior inicializando primero todas las variables locales a cero (en las que llamar a FreeAndNil es seguro y no hará nada). Esto tiene sentido si libera muchas instancias de clase. Así que los dos ejemplos de código a continuación funcionan igual de bien:

Probablemente sea más legible de la siguiente forma:

Nota:
En este ejemplo simple, también podría presentar un argumento válido de que el código debe dividirse en 3 procedimientos separados, uno llamándose entre sí.

Cómo se muestran las excepciones en varias bibliotecas

En el caso de Lazarus LCL, las excepciones generadas durante los eventos (varias devoluciones de llamada asignadas a las propiedades OnXxx de los componentes LCL) se capturarán y darán como resultado un agradable mensaje de diálogo que permite al usuario continuar y detener la aplicación. Esto significa que sus propias excepciones no «salen» de Application.ProcessMessages, por lo que no rompen automáticamente la aplicación. Puede configurar lo que sucede usando TApplicationProperties.OnException. De manera similar, en el caso de Castle Game Engine con CastleWindow: la excepción se captura internamente y da como resultado un buen mensaje de error. Por lo tanto, las excepciones no «salen» de Application.ProcessMessages. Nuevamente, puede configurar lo que sucede usando Application.OnException.

Algunas otras bibliotecas GUI pueden hacer algo similar a lo anterior.

En el caso de otras aplicaciones, puede configurar cómo se muestra la excepción asignando una devolución de llamada global a OnHaltProgram.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio esta protegido por reCAPTCHA y laPolítica de privacidady losTérminos del servicio de Googlese aplican.

El periodo de verificación de reCAPTCHA ha caducado. Por favor, recarga la página.