TRY FINALLY EXCEPT

Материал из GB wiki
Перейти к: навигация, поиск

Функции для обработки исключений (доступны с версии 1.9.0.9).

Синтаксис

TRY(выражение, выражение, ..., FINALLY(выражение, выражение, ...) )
или
TRY(выражение, выражение, ..., EXCEPT(выражение, выражение, ...) )
или
TRY(выражение, выражение, ..., EXCEPT(выражение, выражение, ..., RAISE() ) )

Аргументы

блок TRY
в блоке TRY находятся выражения, выполнение которых нужно проконтролировать
блок FINALLY
в блоке FINALLY находятся выражения, которые нужно выполнить независимо от того, возникло или нет исключение при выполнении блока TRY. Обычно используется для гарантированного освобождения ресурсов, выделенных в блоке TRY.
Фактически FINALLY не обрабатывает исключение, т.е. скрипт будет прерван, если нет никаких обработчиков EXCEPT. Чтобы всё-таки обработать исключение, нужно использовать вложенные конструкции TRY:
TRY(
  TRY(
    ...,
    EXCEPT(
      ...
    )
  ),
  FINALLY(
    ...
  )
)
блок EXCEPT
в блоке EXCEPT находятся выражения, которые будут выполнены только в том случае, если в блоке TRY возникнет исключение. При этом исключение считается обработанным и выполнение скрипта не прерывается стандартным сообщением об ошибке
RAISE()
функция RAISE(), помещённая в блок EXCEPT, возобновляет исключение, проталкивая его во внешний обработчик или, если такового нет - в стандартный обработчик исключений
Объект E
E - объект для работы с ошибками. Например: E.ClassName(), E.Message(), E.DbMessage().
E.DbMessage() содержит оригинальное сообщение из процедуры, если ошибка была при вызове процедуры, либо то же самое что E.Message() во всех остальных случаях

Тип результата

Нет

Примеры

Пример 1.

:SDt:=`aaa`,
TRY(STRTODATE(:SDt),
    EXCEPT(
        INFO(`Ошибка преобразования даты`)
    )
),
INFO(`Продолжаем выполнение...`)

Будут выведены следующие сообщения:

  • "Ошибка преобразования даты"
  • "Продолжаем выполнение..."

и выполнение скрипта будет продолжено.


Пример 2.

:SDt:=`aaa`,
TRY(STRTODATE(:SDt),
  EXCEPT(
    INFO(`Ошибка преобразования даты`),
    RAISE()
  )
),
INFO(`Продолжаем выполнение...`)

Будут выведены следующие сообщения:

  • "Ошибка преобразования даты"
  • "'aaa' is not a valid date and time"

и выполнение скрипта будет прервано.


Пример 3.

TRY(
  /*распределяем ресурсы*/
  :var.str:=TStringList.Create(),
  /*попытка прочитать несуществующий файл*/
  :var.str.LoadFromFile(`C:\0.txt`),
  FINALLY(
    /*ВСЕГДА освобождаем ресурсы*/
    :var.str.Free(),
    INFO(`Освободили ресурсы`)
  )
),
INFO(`Продолжаем выполнение...`)

Будут выведены следующие сообщения:

  • "Освободили ресурсы"
  • "Не удалось открыть файл C:\0.txt"

и выполнение скрипта будет прервано.


Пример 3.1.
Аналогично предыдущему, но с обработкой исключения во вложенном блоке TRY..EXCEPT и, соответственно, продолжением выполнения скрипта.

TRY(
  TRY(
    /*распределяем ресурсы*/
    :var.str:=TStringList.Create(),
    /*попытка прочитать несуществующий файл*/
    :var.str.LoadFromFile(`C:\0.txt`),
    EXCEPT(
      /*обрабатываем исключение*/
      INFO(`Не удалось прочитать файл`)
    )
  ),
  FINALLY(
    /*ВСЕГДА освобождаем ресурсы*/
    :var.str.Free(),
    INFO(`Освободили ресурсы`)
  )
),
INFO(`Продолжаем выполнение...`)

Будут выведены следующие сообщения:

  • "Не удалось прочитать файл"
  • "Освободили ресурсы"
  • "Продолжаем выполнение..."

и выполнение скрипта будет продолжено.


Пример 4.

Можно использовать объект E для работы с ошибками:

:SDt:=`aaa`,
TRY(
  STRTODATE(:SDt),
  EXCEPT(
    INFO(
      `Произошла какая-то ошибка... Определим её тип.`
      + \
      + `Класс ошибки: `
      + E.ClassName()
      + \
      + `Текст ошибки: `
      + E.Message()
    )
  )
),
INFO(`Продолжаем выполнение...`)

Будут выведены следующие сообщения:

  • Произошла какая-то ошибка... Определим её тип.
Класс ошибки: EConvertError
Текст ошибки: 'aaa' is not a valid date and time
в выражении
STRTODATE(:SDt)
  • Продолжаем выполнение...


Пример 5. Использование Exit в блоке Finally:

:var.Res:=
Try(
  aaa,
Finally(
  Exit(`Выходим из Finally, а ошибки нет!`)
 )
),
Info(:var.Res)

Вместо ошибки при обращении к неопределённому полю "aaa", будет выведено сообщение:

  • Выходим из Finally, а ошибки нет!

Связано это с тем, что функция Exit() в ГБ реализована также через исключения, потому ошибка при обращении к полю теряется. Следует избегать использования конструкций, аналогичных вышеприведённой.