Originale-mail to me for new edition

 

Try...except statements

 

Exceptions are handled within try...except statements. For example,

try

  X := Y/Z;

except

  on EZeroDivide do HandleZeroDivide;

end;

This statement attempts to divide Y by Z, but calls a routine named HandleZeroDivide if an EZeroDivide exception is raised.

The syntax of a try...except statement is

try statements except exceptionBlock end

where statements is a sequence of statements (delimited by semicolons) and exceptionBlock is either

·another sequence of statements or

·a sequence of exception handlers, optionally followed by

else statements

An exception handler has the form

on identifier: type do statement

where identifier: is optional (if included, identifier can be any valid identifier), type is a type used to represent exceptions, and statement is any statement.

A try...except statement executes the statements in the initial statements list. If no exceptions are raised, the exception block (exceptionBlock) is ignored and control passes to the next part of the program.

If an exception is raised during execution of the initial statements list, either by a raise statement in the statements list or by a procedure or function called from the statements list, an attempt is made to handle the exception:

·       If any of the handlers in the exception block matches the exception, control passes to the first such handler. An exception handler matches an exception just in case the type in the handler is the class of the exception or an ancestor of that class.

·   If no such handler is found, control passes to the statement in the else clause, if there is one.

·   If the exception block is just a sequence of statements without any exception handlers, control passes to the first statement in the list.

If none of the conditions above is satisfied, the search continues in the exception block of the next-most-recently entered try...except statement that has not yet exited. If no appropriate handler, else clause, or statement list is found there, the search propagates to the next-most-recently entered try...except statement, and so forth. If the outermost try...except statement is reached and the exception is still not handled, the program terminates.

When an exception is handled, the stack is traced back to the procedure or function containing the try...except statement where the handling occurs, and control is transferred to the executed exception handler, else clause, or statement list. This process discards all procedure and function calls that occurred after entering the try...except statement where the exception is handled. The exception object is then automatically destroyed through a call to its Destroy destructor and control is passed to the statement following the try...except statement. (If a call to the Exit, Break, or Continue standard procedure causes control to leave the exception handler, the exception object is still automatically destroyed.)

In the example below, the first exception handler handles division-by-zero exceptions, the second one handles overflow exceptions, and the final one handles all other math exceptions. EMathError appears last in the exception block because it is the ancestor of the other two exception classes; if it appeared first, the other two handlers would never be invoked.

try

 ...

except

  on EZeroDivide do HandleZeroDivide;

  on EOverflow do HandleOverflow;

  on EMathError do HandleMathError;

end;

An exception handler can specify an identifier before the name of the exception class. This declares the identifier to represent the exception object during execution of the statement that follows on...do. The scope of the identifier is limited to that statement. For example,

try

 ...

except

  on E: Exception do ErrorDialog(E.Message, E.HelpContext);

end;

If the exception block specifies an else clause, the else clause handles any exceptions that aren’t handled by the block’s exception handlers. For example,

try

 ...

except

  on EZeroDivide do HandleZeroDivide;

  on EOverflow do HandleOverflow;

  on EMathError do HandleMathError;

else

  HandleAllOthers;

end;

Here, the else clause handles any exception that isn’t an EMathError.

An exception block that contains no exception handlers, but instead consists only of a list of statements, handles all exceptions. For example,

try

 ...

except

  HandleException;

end;

Here, the HandleException routine handles any exception that occurs as a result of executing the statements between try and except.

 

Topic groups

 

See also

Exceptions: Overview

Raising and handling exceptions

Try...finally statements

 

 

译文

 

Try...except语句

 

异常可以在try...except语句中被处理。例如,

try

  X := Y/Z;

except

  on EZeroDivide do HandleZeroDivide;

end;

这里的语句试图用Y除以Z,而如果引发一个EZeroDivide异常时则调用一个名为HandleZeroDivide的例程。

 

try...except语句的语法是

try statements except exceptionBlock end

这里的statemens是一个语句序列(分号隔开的),exceptionBlock是下列二者之一

·另一个语句序列,或者

·异常处理程序的序列,可选择地跟随

else statements

 

异常处理程序具有如下形式

on identifier: type do statement

这里的identifier:是可选的(如果包括,则identifier可以是任何有效标识符),type是一个用于表示异常的类型,statement是任何语句。

 

try...except语句执行最初的statements语句序列。如果没有异常被引发,那么异常块(exceptionBlock)被忽略并且控制被传递到程序的下一部分。

如果在执行最初的statements序列中引发了异常,那么,或者被statements序列中的raise语句,或者被statements序列中的过程或函数调用,都将尝试完成处理异常:

·       如果异常块中的任意一个处理程序与引发的异常相匹配,那么控制被传递到第一个匹配的项。异常处理程序与异常相匹配,是指处理程序中type表示的类与是异常所属的类或其祖先类。

·   如果没有发现匹配的异常处理程序,那么控制被传递到else子句中的statements语句序列(如果有该语句序列)。

·   如果异常块是一个不含有任何异常处理程序的语句序列,那么控制被传递到语句序列中的第一条语句。

如果上述条件都不满足,那么将继续在下一个最近的入口try...except语句(尚未退出之前)的异常块中搜索。如果没有发现合适的处理程序、else子句或语句序列,那么搜索将延伸到下一个最近的入口try...except语句,等等。如果最外层的try...except语句被搜索过并且异常仍然没有被处理,那么程序终止。

当一个异常被处理时,堆栈将追踪回溯到包含了处理发生时try...except语句的过程或函数,并且控制被传递到执行过的异常处理程序、else子句或相关的语句序列。这一处理过程将丢弃所有在进入异常被处理的try...except语句之后出现的过程和函数调用。这时异常对象通过对其Destroy析构器的调用被自动释放,并且控制被传递到随后的try...except语句。(如果对ExitBreakContinue等标准过程的调用导致控制离开了异常处理程序,那么异常对象仍然会自动销毁。)

下面的例子中,第一个异常处理程序处理零除异常,第二个处理溢出异常,最后一个处理所有的数学异常。EMathError异常出现在异常块的最后,是因为它是其他两个异常类的祖先类;如果它出现在首位,那么其他两个异常处理程序将决不会被调用。

try

 ...

except

  on EZeroDivide do HandleZeroDivide;

  on EOverflow do HandleOverflow;

  on EMathError do HandleMathError;

end;

 

异常处理程序可以在异常类的名称之前指定一个标识符。如此声明的标识符用于在随后的on...do语句执行的全程中表示当前的异常对象。标识符的作用域仅限于on...do语句。例如,

try

 ...

except

  on E: Exception do ErrorDialog(E.Message, E.HelpContext);

end;

 

如果异常块指定了else子句,那么else子句负责处理在当前块中尚未被异常处理程序处理的其他任何异常。例如,

try

 ...

except

  on EZeroDivide do HandleZeroDivide;

  on EOverflow do HandleOverflow;

  on EMathError do HandleMathError;

else

  HandleAllOthers;

end;

这里,else子句处理任何非EMathError异常。

 

异常块中没有任何异常处理程序,而只是由语句序列组成,这样的异常块将处理所有的异常。例如,

try

 ...

except

  HandleException;

end;

这里,HandleException例程负责处理在tryexcept之间语句执行导致出现的任何异常。

 

主题组

 

相关主题

异常:概述

引发和处理异常

Try...finally语句