Установка состояния ERROR
Кроме уже рассмотренных способов программной установки состояния ERROR (опция RETURN ERROR во фразе ON ERROR и в операторе UNDO), это может быть сделано с помощью оператора RETURN.
Оператор RETURN позволяет осуществить немедленный выход из блока. Немедленный – означает, что выполнение блока останавливается на операторе RETURN, и управление передается в вызывающий блок, без учета промежуточных блоков.
Оператор осуществляет выход из внутренней или внешней процедуры, из функции, триггерного блока, триггера базы данных, блока метода класса, блока конструктора класса, блока доступа к свойствам – и возвращает управление вызывающей процедуре, функции, методу и т.д. Если таковой нет – происходит возврат в инструментальную среду, вызвавшую процедуру, или в операционную систему.
Синтаксис оператора:
RETURN
[ return-value |
ERROR [ return-value | error-object-expression ] |
NO-APPLY ]
Здесь:
return-value Значение, которое оператор RETURN возвращает вызывающему блоку, с установкой или без установки состояния ERROR.
ERROR Устанавливает состояние ERROR в вызывающем блоке.
error-object-expression Используется при структурной обработке ошибок. Будет рассмотрено ниже.
NO-APPLY Подавляет стандартную обработку события пользовательского интерфейса.
Состояние ERROR после возврата по RETURN ERROR может быть установлено при выполнении следующих операторов вызывающей процедуры:
- Оператор RUN, вызывающий процедуру.
- Любой оператор, вызывающий метод класса.
- Любой оператор, вызывающий функцию NEW или DYNAMIC-NEW для создания экземпляра класса (вызывает указанный конструктор и все другие конструкторы из иерархии класса).
- Любой оператор, обращающийся к свойству класса.
Опция ERROR может быть указана в процедуре, триггере базы данных, методе класса, конструкторе, методе доступа к свойству. Однако, опцию ERROR нельзя указывать в блоке триггера пользовательского интерфейса или деструкторе. Любые значения, установленные для OUTPUT или INPUT-OUTPUT параметров до выполнения RETURN ERROR, не возвращаются вызывающему блоку.
Следующая таблица (Таблица 8) показывает, как получить доступ к значению return-value в вызывающей программе в различных случаях:
Таблица 8. Доступ к возвращаемому значению RETURN
Ситуация |
Доступ |
return-value определено без опции ERROR в процедурном или триггерном блоке | Функция RETURN-VALUE. |
return-value определено для non-VOID метода или для пользовательской функции без опции ERROR | Обращение к методу или функции по ссылке в выражении. |
return-value определено с опцией ERROR | Функция RETURN-VALUE. Для структурного обработчика ошибок, также, свойство ReturnValue объекта ошибки (error object) |
Пользовательские функции.
Пользовательские функции, определенные оператором FUNCTION, возвращают значение определенного типа, как описано в заголовке функции. Для возврата этого значения в теле функции используется оператор RETURN. Это не позволяет использовать в функциях оператор RETURN ERROR таким же образом, как это делается в других блоках.
RETURN ERROR в функции не устанавливает состояние ERROR в вызывающем блоке. Вместо этого он присваивает неопределенное значение возвращаемому значению функции. Соответственно, это может быть использовано для проверки и обработки ошибки в функциях:
IF ErrorTest() = ? THEN DISPLAY “Error in ErrorTest function.”.
В принципе, тот же эффект достигается при возврате из функции по RETURN ?. Использование RETURN ERROR в функциях, по идее, должно улучшать читаемость кода. С другой стороны, так как состояние ERROR при этом не устанавливается, это тоже может вводить в заблуждение. В качестве альтернативы можно использовать препроцессорную переменную:
&SCOPED-DEFINE FUNCTION-ERROR ?
RETURN {&FUNCTION-ERROR}.
Выбор за Вами, важно лишь придерживаться единого стиля при обработке ошибок в Ваших функциях.
Еще одно замечание: возврат неопределенного значения в качестве признака ошибки в функции не позволяет точно определить причину ошибки, если возможно несколько вариантов. Решить эту проблему можно, но лишь поступившись строгостью интерфейса функции, либо включив обработчик ошибок непосредственно в функцию. Это еще один аргумент против создания чересчур сложных функций.