DMarlon Studio

Lesson 7 · 7 of 20

Exceptions · Pascal

Raise and catch exceptions in Object Pascal with raise and try/except, and create your own exception classes for your application's errors.

Pascal · Exceptions in DMarlon Studio: the example's code and its output in the terminal

An exception is an object that breaks the normal flow when something goes wrong. They all descend from Exception (in the SysUtils unit), and declaring your own takes one line: EOutOfStock = class(Exception). By convention, their names start with E.

Order checks the request and, when it cannot fulfil it, says so with `raise`: raise EOutOfStock.CreateFmt(...) builds the exception with a Format-style message and throws it. The procedure stops right there and execution jumps to the nearest handler. StrToInt('ten') throws one of its own, EConvertError, without you writing anything.

A `try ... except` block catches whatever is raised inside it. Each `on E: Class do` handles one type and gives you the object in E, with its Message and ClassName. They are tried in order, so specific types go first and Exception, which catches everything, goes last: that is why the EArgumentException for the order of 0 lands on the final line.

Because the try sits inside the loop, a bad request does not stop the rest: all four are processed and the program ends with All requests handled. The exception object is freed by the except block itself; you do not call Free.

Code · main.pas

program main;uses SysUtils;type  EOutOfStock = class(Exception);  // our own exception classconst  Stock = 5;  Requests: array[0..3] of String = ('3', 'ten', '0', '8');procedure Order(const qtyText: String);var qty: Integer;begin  qty := StrToInt(qtyText);  // raises EConvertError if it is not a number  if qty <= 0 then    raise EArgumentException.Create('quantity must be positive');  if qty > Stock then    raise EOutOfStock.CreateFmt('only %d left, %d requested', [Stock, qty]);  WriteLn('Order for ', qty, ' accepted');end;var request: String;begin  for request in Requests do    try      Order(request);    except      on E: EOutOfStock do WriteLn('Out of stock: ', E.Message);      on E: EConvertError do WriteLn('Not a number: ', E.Message);      on E: Exception do WriteLn(E.ClassName, ': ', E.Message);    end;  WriteLn('All requests handled');end.

Output · fpc main.pas && ./main

Order for 3 accepted
Not a number: "ten" is an invalid integer
EArgumentException: quantity must be positive
Out of stock: only 5 left, 8 requested
All requests handled

Key points

  • raise throws an exception and stops execution.
  • Your exceptions inherit from Exception and start with E.
  • on E: Class do catches one specific type.
  • Put specific types before Exception.
  • The exception object is freed once it is caught.

Exercise

Create EMaxOrder = class(Exception) and raise it when the quantity is over 100; add '250' to Requests and a handler of its own that prints "Too many units".