На этом шаге мы рассмотрим преднамеренную генерацию исключений.
В некоторых случаях возникает необходимость искусственно сгенерировать исключение. Это может потребоваться в следующих случаях.
Try <Операторы внешнего блока.> Try <Операторы, при выполнении которых возможно исключение.> Except On <Тип исключения> Do Begin <Обработка исключений, сгенерированных во внутреннем блоке.> Raise;//Повторная генерация исключения. End; <Операторы внешнего блока. При возникновении исключения не выполняются.> Except <Обработка исключений и внутреннего, и внешнего блоков.> End;
Raise <исключение>; или Raise <тип исключения>.<конструктор>; .
Здесь исключение - имя созданного Вами объекта исключения, тип исключения - любое исключение из предопределенных в Delphi, конструктор - любой из возможных конструкторов. Например, при анализе следующей конструкции:
If Edit1.Text='' Then Raise EZeroDivide.Create ('Не задана требуемая информация');
если пользователь не задал требуемой информации, то будет сгенерировано исключение типа EZeroDivide (якобы целочисленное деление на нуль). При отсутствии обработчика этого исключения пользователь увидит на экране диалоговое окно с фразой: "Не задана требуемая информация". Так можно использовать предопределенные исключения для информации об ошибках, никакого отношения не имеющие к их первоначальному смыслу. Однако для этих целей лучше всего использовать созданные пользователем классы исключений, к рассмотрению которых мы приступаем.
Как известно, классы исключений являются производными от класса Exception. Поэтому при создании нового класса данный класс нужно указывать в качестве родителя.
Создаваемые классы можно разделить на две большие группы.
Type <имя класса исключения> = Class(Exception);
. . . . . . Type ENoInf = Class (Exception);//Создание нового класса. . . . . . . //Генерация исключения. Raise ENoInf.Create('Не задана требуемая информация'); . . . . . . //Его обработка. On ENoInf Do MessageDlg ('Укажите цену товара.', mtWarning, [mbOk], 0); . . . . . .
Для конкретизации сообщений можно также формировать текст соответствующего сообщения при генерации исключения. Например, при работе с программой нужно задать серию и номер паспорта. Вот как может выглядеть блок такой проверки:
. . . . . . S:=''; If EditSer.Text='' Then S:='серию';//Проверка серии. If EditNom.Text='' Then //Проверка номера паспорта. If S='' Then S:='номер' Else S:=S+' и номер'; If S<>'' Then Raise ENoInf.CreateFmt('Укажите %s паспорта',[S]); . . . . . .
Type <имя класса исключения> = Class (Exception) <поля> end;
Type EMy = Class (Exception) Public Enum: Integer; End;
создает класс исключения с именем EMy, имеющий открытое поле Enum, в которое Вы можете заносить, например, идентификатор возникшей исключительной ситуации. Использовать такой класс можно следующим образом:
. . . . . . Type EMy = Class (Exception) Public Enum: Integer; End; Var Exc: EMy; //Именованный объект исключения. . . . . . . Try . . . . . . If <условие наличия ошибки> Then Begin Exc:=EMy.Create(<текст сообщения>); Exc.Enum:=<идентификатор ошибки>; Raise Exc;//Генерация исключения. End; . . . . . . Except On EMy Do Case Exc.Enum Of 1: <набор действий 1>; 2: <набор действий 2>; . . . . . . End;//Конец блока Case. End;//Конец блока Try.
В заключение разберем исключение EAbort, несколько отличающееся от рассмотренных ранее. Генерация этого исключения также прерывает выполнение программы. Однако если оно не обрабатывается приложением, то разрушается без всяких дополнительных сообщений (без вывода диалогового окна с сообщением об ошибке).
Простейший способ генерации этого исключения - вызов процедуры Abort:
If <проверка условия прерывания> Then Abort;
Обычное применение EAbort - прерывание вычислений при выполнении некоторого условия окончания или
нажатие какой-либо комбинации клавиш. Таким образом, генерация исключения процедурой Abort
эквивалентна применению Exit или Break, с той только разницей, что Break
прерывает выполнение цикла и управление передается следующему за циклом оператору; Exit прерывает
выполнение текущей процедуры и управление передается в вызвавшую ее процедуру, а
Abort прерывает текущую процедуру и все вызвавшие ее процедуры. При необходимости перехватить
исключение на каком-то промежуточном уровне, расположив там блок Try...Except
и вставив туда оператор On следующего вида:
On EAbort Do ....;
На следующем шаге мы рассмотрим содержимое пункта меню View.