TRY FINALLY EXCEPT — различия между версиями
Alexey (обсуждение | вклад) |
Alexey (обсуждение | вклад) |
||
(не показано 15 промежуточных версий этого же участника) | |||
Строка 2: | Строка 2: | ||
{{Функция ГБ | {{Функция ГБ | ||
|Название=TRY...FINALLY...EXCEPT | |Название=TRY...FINALLY...EXCEPT | ||
− | |Описание=Функции для | + | |Описание=Функции для обработки исключений (доступны с версии 1.9.0.9). |
− | |Синтаксис='''TRY'''(''выражение, выражение, ...'', '''FINALLY'''(''выражение, выражение, ...'') | + | |Синтаксис='''TRY'''(''выражение, выражение, ...'', '''FINALLY'''(''выражение, выражение, ...'') ) |
<br/>или | <br/>или | ||
− | <br/>'''TRY'''(''выражение, выражение, ...'', '''EXCEPT'''(''выражение, выражение, ...'')) | + | <br/>'''TRY'''(''выражение, выражение, ...'', '''EXCEPT'''(''выражение, выражение, ...'') ) |
+ | <br/>или | ||
+ | <br/>'''TRY'''(''выражение, выражение, ...'', '''EXCEPT'''(''выражение, выражение, ...'', '''RAISE'''() ) ) | ||
|Аргументы= | |Аргументы= | ||
{{Аргумент | {{Аргумент | ||
− | |Название= | + | |Название=блок TRY |
− | |Пояснение= | + | |Пояснение=в блоке TRY находятся выражения, выполнение которых нужно проконтролировать |
+ | }}<br/>{{Аргумент | ||
+ | |Название=блок FINALLY | ||
+ | |Пояснение=в блоке FINALLY находятся выражения, которые нужно выполнить независимо от того, возникло или нет исключение при выполнении блока TRY. Обычно используется для гарантированного освобождения ресурсов, выделенных в блоке TRY.<br>Фактически FINALLY не обрабатывает исключение, т.е. скрипт будет прерван, если нет никаких обработчиков EXCEPT. Чтобы всё-таки обработать исключение, нужно использовать вложенные конструкции TRY: | ||
+ | TRY( | ||
+ | TRY( | ||
+ | ..., | ||
+ | EXCEPT( | ||
+ | ... | ||
+ | ) | ||
+ | ), | ||
+ | FINALLY( | ||
+ | ... | ||
+ | ) | ||
+ | ) | ||
+ | }}<br/>{{Аргумент | ||
+ | |Название=блок EXCEPT | ||
+ | |Пояснение=в блоке EXCEPT находятся выражения, которые будут выполнены только в том случае, если в блоке TRY возникнет исключение. При этом исключение считается обработанным и выполнение скрипта не прерывается стандартным сообщением об ошибке | ||
+ | }}<br/>{{Аргумент | ||
+ | |Название=RAISE() | ||
+ | |Пояснение=функция RAISE(), помещённая в блок EXCEPT, возобновляет исключение, проталкивая его во внешний обработчик или, если такового нет - в стандартный обработчик исключений | ||
}}<br/>{{Аргумент | }}<br/>{{Аргумент | ||
− | |Название= | + | |Название=Объект E |
− | |Пояснение= | + | |Пояснение=E - объект для работы с ошибками. Например: E.ClassName(), E.Message(), E.DbMessage().<br>E.DbMessage() содержит оригинальное сообщение из процедуры, если ошибка была при вызове процедуры, либо то же самое что E.Message() во всех остальных случаях |
}} | }} | ||
|Пример=Пример 1. | |Пример=Пример 1. | ||
− | '''TRY'''(< | + | :SDt:=`aaa`, |
+ | '''TRY'''(STRTODATE(:SDt), | ||
+ | '''EXCEPT'''( | ||
+ | INFO(`Ошибка преобразования даты`) | ||
+ | ) | ||
+ | ), | ||
+ | INFO(`Продолжаем выполнение...`) | ||
+ | |||
+ | Будут выведены следующие сообщения: | ||
+ | * "Ошибка преобразования даты" | ||
+ | * "Продолжаем выполнение..." | ||
+ | и выполнение скрипта будет продолжено. | ||
+ | |||
+ | <br> | ||
+ | Пример 2. | ||
+ | :SDt:=`aaa`, | ||
+ | '''TRY'''(STRTODATE(:SDt), | ||
+ | '''EXCEPT'''( | ||
+ | INFO(`Ошибка преобразования даты`), | ||
+ | '''RAISE'''() | ||
+ | ) | ||
+ | ), | ||
+ | INFO(`Продолжаем выполнение...`) | ||
+ | |||
+ | Будут выведены следующие сообщения: | ||
+ | * "Ошибка преобразования даты" | ||
+ | * "'aaa' is not a valid date and time" | ||
+ | и выполнение скрипта будет прервано. | ||
+ | |||
+ | <br> | ||
+ | Пример 3. | ||
+ | '''TRY'''( | ||
+ | /*распределяем ресурсы*/ | ||
+ | :var.str:=TStringList.Create(), | ||
+ | /*попытка прочитать несуществующий файл*/ | ||
+ | :var.str.LoadFromFile(`C:\0.txt`), | ||
+ | '''FINALLY'''( | ||
+ | /*ВСЕГДА освобождаем ресурсы*/ | ||
+ | :var.str.Free(), | ||
+ | INFO(`Освободили ресурсы`) | ||
+ | ) | ||
+ | ), | ||
+ | INFO(`Продолжаем выполнение...`) | ||
+ | |||
+ | Будут выведены следующие сообщения: | ||
+ | * "Освободили ресурсы" | ||
+ | * "Не удалось открыть файл C:\0.txt" | ||
+ | и выполнение скрипта будет прервано. | ||
+ | |||
+ | <br> | ||
+ | Пример 3.1.<br>Аналогично предыдущему, но с обработкой исключения во вложенном блоке TRY..EXCEPT и, соответственно, продолжением выполнения скрипта. | ||
+ | '''TRY'''( | ||
+ | '''TRY'''( | ||
+ | /*распределяем ресурсы*/ | ||
+ | :var.str:=TStringList.Create(), | ||
+ | /*попытка прочитать несуществующий файл*/ | ||
+ | :var.str.LoadFromFile(`C:\0.txt`), | ||
'''EXCEPT'''( | '''EXCEPT'''( | ||
− | + | /*обрабатываем исключение*/ | |
+ | INFO(`Не удалось прочитать файл`) | ||
+ | ) | ||
+ | ), | ||
+ | '''FINALLY'''( | ||
+ | /*ВСЕГДА освобождаем ресурсы*/ | ||
+ | :var.str.Free(), | ||
+ | INFO(`Освободили ресурсы`) | ||
+ | ) | ||
+ | ), | ||
+ | INFO(`Продолжаем выполнение...`) | ||
+ | |||
+ | Будут выведены следующие сообщения: | ||
+ | * "Не удалось прочитать файл" | ||
+ | * "Освободили ресурсы" | ||
+ | * "Продолжаем выполнение..." | ||
+ | и выполнение скрипта будет продолжено. | ||
+ | |||
+ | <br> | ||
+ | Пример 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) | ||
+ | * Продолжаем выполнение... | ||
− | + | <br> | |
− | + | Пример 5. | |
− | <br | + | Использование Exit в блоке Finally: |
− | + | :var.Res:= | |
− | + | '''Try'''( | |
− | + | aaa, | |
− | + | '''Finally'''( | |
− | + | '''Exit'''(`Выходим из Finally, а ошибки нет!`) | |
− | + | ) | |
− | + | ), | |
+ | '''Info'''(:var.Res) | ||
+ | Вместо ошибки при обращении к неопределённому полю "aaa", будет выведено сообщение: | ||
+ | * Выходим из Finally, а ошибки нет! | ||
+ | Связано это с тем, что функция Exit() в ГБ реализована также через исключения, потому ошибка при обращении к полю теряется. Следует избегать использования конструкций, аналогичных вышеприведённой. | ||
}} | }} |
Текущая версия на 12:20, 20 мая 2022
Функции для обработки исключений (доступны с версии 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() в ГБ реализована также через исключения, потому ошибка при обращении к полю теряется. Следует избегать использования конструкций, аналогичных вышеприведённой.