Re: Handling exceptions in functions



Hi there

I was wondering if there's a better way to handle exceptions in functions calls.
What I would like to achieve is trivial, if any error happens in the function,
returns false and raise the exception, otherwise return true.

This cannot happen - you cannot return a value *and* raise an exception.
You have to do one or the other. Raising an exception (or not catching
an exception which occurs during the course of your function) means the
function will not return a value.

// This is just a sample. It can be any kind of exception.
procedure DoSomething( aParam : Integer );
begin
if aParam=0 then Raise Exception.Create('Something terrible happened!');
end;

OK, this is valid.

//# no hints; works fine but I cannot trap the error;
function TMyObject.MyFunction( aParam1, aParam2 : Integer ) : Boolean;
begin
try
DoSomething( aParam1 );
DoSomething( aParam2 );
Result := True;
except
Result := False;
end;
end;

This should work using the DoSomething function defined above - are you sure you are not seeing the IDE intercept your exception during
debugging? This is normal, but can be turned off in the debugging
options (something like Tools-Options-Debugger in the Delphi menu).
Run your exe outside the Delphi IDE, does it now appear to work as you
think it should?

// I suspect this one will return anything on error
function TForm1.MyFunction( aParam1, aParam2 : Integer ) : Boolean;
begin
Result := False; //# Hint : Value assigned never used
try
DoSomething(aParam1);
DoSomething(aParam2);
Result := True;
except
Raise;
end;
end;

This is pointless. It just re-raises any exception which has already
been raised.

// I suspect this one will return anything on error
function TMyObject.MyFunction2( aParam1, aParam2 : Integer ) : Boolean;
begin
try
DoSomething( aParam1 );
DoSomething( aParam2 );
Result := True;
except
on E:Exception do begin
Result := False; // #Hint: Value assigned never used
Raise;
end;
end;
end;

Again, this is pointless, and the hint is correct.
Raising an exception (or letting exceptions escape from your function,
means the return value will not be set, or used, by the calling
function.


//# no hints, but never passes by Result := False;
//# No warnings too... Shouldn't this be a bug?
function TMyObject.MyFunction3( aParam1, aParam2 : Integer ) : Boolean;
begin
try
DoSomething( aParam1 );
DoSomething( aParam2 );
Result := True;
except
on E:Exception do begin
Raise;
Result := False;
end;
end;
end;

Same as above.

//This one returns always true
function TMyObject.MyFunction4( aParam1, aParam2 : Integer ) : Boolean;
begin
Result := True;
try
DoSomething( aParam1 );
DoSomething( aParam2 );
except
on E:Exception do begin
Result := False; // #Hint: Value assigned never used
Raise;
end;
end;
end;

Same as above.

// Works fine, but I have to pass one extra parameter.
// Some functions are using one of the above "templates", and changing
// all of them to meet this one will really be my last resource. A lot of
// callers depends on trapping exceptions, and using the method below, no more
// exceptions will raise. You might guess I won't sleep for sometime.
// Before start changing, I thought to post here and hope someone can shed some
// light.
function TMyObject.MyFunction5(aParam1, aParam2: Integer;
var aErrMsg: String): Boolean;
begin
try
DoSomething(aParam1);
DoSomething(aParam2);
Result := True;
except
on E:Exception do begin
Result := False;
aErrMsg := E.Message;
end;
end;
end;

This is valid.

How you want to handle exceptions depends completely on what you
want your code to do. Exceptions are designed to allow programs
to cope with expected and unexpected errors.

So, for example, expected errors in a program may be (for example)
Disk full.
Read-only file, can't save
etc...

Unexpected errors are, well, unexpected!
With the expected errors, you can use the exception handler to
catch and deal with those errors (for example, for a read-only file,
let the user select another file), and let unhandled errors
escape to a higher level of your program, since you cannot
realistically do anything to fix the error.

So ideally, your exception handlers should look something like this:

try
...
except
on EDiskFullError do begin
// expected error - handle here
end
on EReadOnlyFile do begin
// another expected error - do something else
end
else raise; // unexpected errors - can't fix these

Hope this helps.

Cheers,

Chris
.



Relevant Pages

  • Re: catch (...)
    ... "Tom Groszko" wrote in message ... > {dosomething(); ... > {report some error ... nice enough to base his exception class on std::exception you should be able ...
    (comp.lang.cpp)
  • Re: finalize()
    ... public void doSomething() throws Exception { ... File file = null; ... You failed to catch the Exception that doSomethingmight throw. ...
    (comp.lang.java.programmer)
  • Re: Is it possible for a try...finally...end construct to fail?
    ... :) try/finally and try/except are completely different ... side effect of Delphi's global exception handler). ... Probably show an error message to the user at this ...
    (borland.public.delphi.language.objectpascal)
  • Re: preserve exception within try .. finally
    ... The exception raised by doSomething() travels all the way up the call stack ... getResource() # don't free if it cannot be acquired ... I think that the canHandleIttest and the reraising is not very common, ...
    (comp.lang.python)
  • Re: funny exception (Error: 208, Severity: 16, State: 1)
    ... Some error 208 exceptions are handled internally by SQL Server and not ... These expected errors occur when you reference an ... I can't definitively say why you sometimes don't see the exception. ... "Frank Uray" wrote in message ...
    (microsoft.public.sqlserver.programming)

Loading