# Exception Handling
Exceptions provide a structured way to handle runtime errors and unexpected conditions.
## Try...Except
Use `try...except` to catch and handle exceptions. This allows your program to recover from errors gracefully rather than crashing.
```pascal
var data : array of Integer := [ 1, 2, 3 ];
try
PrintLn(data[10]);
except
on E: Exception do
PrintLn('Error: ' + E.Message);
end;
// OUTPUT
// Error: Upper bound exceeded! Index 10*
```
## Try...Finally
Use `try...finally` to ensure code runs regardless of whether an exception occurs. This is essential for resource cleanup, such as closing files or freeing memory.
```pascal
PrintLn('Starting');
try
PrintLn('Working...');
finally
PrintLn('Cleanup');
end;
// OUTPUT
// Starting
// Working...
// Cleanup
```
## Combined Try...Except...Finally
You can nest try blocks or combine them to handle errors and ensure cleanup. A common pattern is protecting a resource that must be closed even if an operation fails.
```pascal
var connectionOpen := True;
try
try
// Perform work that might fail
raise new Exception('Connection lost');
except
on E: Exception do
PrintLn('Caught: ' + E.Message);
end;
finally
connectionOpen := False;
PrintLn('Connection closed');
end;
// OUTPUT
// Caught: Connection lost
// Connection closed
```
## Raising Exceptions
You can raise exceptions using the `raise` keyword.
```pascal
procedure CheckAge(age: Integer);
begin
if age < 0 then
raise new Exception('Age cannot be negative');
end;
try
CheckAge(-5);
except
on E: Exception do
PrintLn(E.Message);
end;
// OUTPUT
// Age cannot be negative
```
## The "on...do" Syntax
You can handle specific exception types.
```pascal
type EMyError = class(Exception);
try
raise new EMyError('Custom error');
except
on E: EMyError do
PrintLn('Specific catch: ' + E.Message);
on E: Exception do
PrintLn('General catch: ' + E.Message);
end;
// OUTPUT
// Specific catch: Custom error
```
### Catch-All "else"
You can use an `else` clause to catch any exception that wasn't matched by previous `on` blocks.
```pascal
try
raise new Exception('Something went wrong');
except
on E: EAssertionFailed do
PrintLn('Assertion failed');
else
PrintLn('Caught unknown error: ' + ExceptObject.Message);
end;
// OUTPUT
// Caught unknown error: Something went wrong
```
## Exception Object
Within an `except` block, the `ExceptObject` function returns the exception instance being handled.
```pascal
try
raise new Exception('Fail');
except
PrintLn(ExceptObject.Message);
end;
// OUTPUT
// Fail
```
## Re-raising Exceptions
You can re-raise the current exception using `raise` with no arguments.
```pascal
try
try
raise new Exception('Critical failure');
except
PrintLn('Logging error...');
raise; // Re-throw to outer handler
end;
except
on E: Exception do
PrintLn('Outer catch: ' + E.Message);
end;
// OUTPUT
// Logging error...
// Outer catch: Critical failure
```
:::info
### Exception Best Practices
* **Catch specific exceptions** whenever possible rather than using a general `on E: Exception`.
* **Use finally blocks** to ensure resources like database connections or temporary files are always closed.
* **Don't suppress exceptions** with an empty `except` block unless you have a very specific reason to do so.
:::
Exception Handling
Exceptions provide a structured way to handle runtime errors and unexpected conditions.
Try...Except
Use try...except to catch and handle exceptions. This allows your program to recover from errors gracefully rather than crashing.
var data :arrayofInteger:=[1,2,3];try
PrintLn(data[10]);excepton E:Exceptiondo
PrintLn('Error: '+ E.Message);end;
Result
Error: Upper bound exceeded! Index 10*
Try...Finally
Use try...finally to ensure code runs regardless of whether an exception occurs. This is essential for resource cleanup, such as closing files or freeing memory.
You can nest try blocks or combine them to handle errors and ensure cleanup. A common pattern is protecting a resource that must be closed even if an operation fails.
var connectionOpen :=True;trytry// Perform work that might failraisenewException('Connection lost');excepton E:Exceptiondo
PrintLn('Caught: '+ E.Message);end;finally
connectionOpen :=False;
PrintLn('Connection closed');end;
Result
Caught: Connection lost
Connection closed
Raising Exceptions
You can raise exceptions using the raise keyword.
procedure CheckAge(age:Integer);beginif age <0thenraisenewException('Age cannot be negative');end;try
CheckAge(-5);excepton E:Exceptiondo
PrintLn(E.Message);end;
Result
Age cannot be negative
The "on...do" Syntax
You can handle specific exception types.
type EMyError =class(Exception);tryraisenew EMyError('Custom error');excepton E: EMyError do
PrintLn('Specific catch: '+ E.Message);on E:Exceptiondo
PrintLn('General catch: '+ E.Message);end;
Result
Specific catch: Custom error
Catch-All "else"
You can use an else clause to catch any exception that wasn't matched by previous on blocks.
tryraisenewException('Something went wrong');excepton E: EAssertionFailed do
PrintLn('Assertion failed');else
PrintLn('Caught unknown error: '+ ExceptObject.Message);end;
Result
Caught unknown error: Something went wrong
Exception Object
Within an except block, the ExceptObject function returns the exception instance being handled.