Pieter B
Pieter B

Reputation: 1967

Are there exceptions that aren't caught by general E : Exception?

I was wondering if there are exceptions/errors, which do make your code jump into an except block but aren't handled by E : exception.

 try
   i := StrToInt(s);
   {...do a lot more...}
 except
   on E : EConvertError do begin
     ShowMessage('You need to input a valid number.');
   end;
   on E : Exception do begin
     ShowMessage('Something went wrong.');
     Raise; 
   end;
 end;

Is there a way that a program could have an error that would ignore both statements in this except block? Or should I do it like this :

 try
   i := StrToInt(s);
   {...do a lot more...}
 except
   on E : EConvertError do begin
     ShowMessage('You need to input a valid number.');
   end;
   else begin  // swapped on e : Exception with else
     ShowMessage('Something went wrong.');
     Raise; 
   end;
 end;

Upvotes: 3

Views: 489

Answers (1)

David Heffernan
David Heffernan

Reputation: 613461

You can throw anything that derives from TObject. In order to catch every such class you'd need to specify TObject in your on statement.

From the documentation:

Exception types are declared just like other classes. In fact, it is possible to use an instance of any class as an exception, but it is recommended that exceptions be derived from the SysUtils.Exception class defined in SysUtils.

In reality I know of no code that throws anything that does not derive from Exception, although @TLama points out one example in a legacy deprecated VCL class in the comments. Certainly StrToInt only throws Exception descendents.

If you don't need to access the exception object you can use a plain except clause without an on statement.

try
  ....
except 
  // deal with all exceptions
end;

Or you can use the else clause of an on statement as a catch all, again you won't get immediate access to the exception object.

Otherwise you can specify a base class for the exceptions that you wish to catch. For instance on E: TObject catches everything derived from TObject.

So, as we see, it is possible that things not derived from Exception may be thrown. But you must ask yourself if your code ever does that? If not then it makes most sense to test for Exception in your catch all handlers. That will give you access to the members of Exception. Of course, one does wonder why you have a catch all exception handler. Their existence are often indication of poor design.

Continuing the theme of StrToInt, you only need to catch EConvertError. That's what is raised when the conversion fails. You should ignore any other exception class as, in your example, the code won't know what to do with anything else. One of the goals of writing exception handling code is to handle what you know how to deal with, and ignore everything else.

In fact, TryStrToInt is what you need here:

if TryStrToInt(s, i) then
  // do stuff with i
else
  // deal with conversion error

This obviates the need to handle any exceptions and makes your code far more readable.

I know that StrToInt is just an example, but it serves quite well to demonstrate the benefits of trying to avoid handling exceptions.

Upvotes: 7

Related Questions