In meinem Lieblingsthread "Eure besten Quellcode Kommentare..." wurde folgender Quellcode Kommentar gesendet.
Delphi-Quellcode:
{$IFDEF MSWINDOWS}
procedure DLLShutdown;
stdcall;
begin
try
if @DLLShutdownProc <>
nil then
DLLShutdownProc;
finally
// eat all exception.
end;
end;
{$ENDIF MSWINDOWS}
Die DLLShutdown-Methode die ich gepostet habe ist übrigens aus der System.pas. (10.3.2)
Genau so geschrieben und kommentiert.
Da es wohl auch bei Borland /Embarcadero / Idera Leute gibt, die sich noch nicht richtig mit dem Thema befasst haben, habe ich hier mal eine kleine Zusammenfassung geschrieben.
try ... finally ... end; Block
Delphi-Quellcode:
...
WriteLn('
Null - ohne Exception');
try
WriteLn('
Eins');
WriteLn('
Zwei');
WriteLn('
Drei');
finally
WriteLn('
Vier');
end;
// hier wird die Exception nochmal geworfen (analog raise)
WriteLn('
Fünf');
...
WriteLn('
Null - mit Exception');
try
WriteLn('
Eins');
WriteLn(StrToInt('
Zwei'));
WriteLn('
Drei');
finally
WriteLn('
Vier');
end;
// hier wird die Exception nochmal geworfen (analog raise)
WriteLn('
Fünf');
...
Gibt Ausgabe:
Code:
...
Null - ohne
Exception
Eins
Zwei
Drei
Vier
Fünf
Null - mit
Exception
Eins
Vier
Exception
Vier wird auf jeden Fall ausgeführt. Egal ob eine
Exception auftritt oder nicht.
try ... except ... end; Block
Delphi-Quellcode:
...
WriteLn('
Null - Ohne Exception');
try
WriteLn('
Eins');
WriteLn('
Zwei');
WriteLn('
Drei');
except
WriteLn('
Vier');
end;
WriteLn('
Fünf');
...
WriteLn('
Null - mit Exception');
try
WriteLn('
Eins');
WriteLn(StrToInt('
Zwei'));
WriteLn('
Drei');
except
WriteLn('
Vier');
end;
WriteLn('
Fünf');
...
Gibt Ausgabe:
Code:
...
Null - Ohne
Exception
Eins
Zwei
Drei
Fünf
Null - mit
Exception
Eins
Vier
Fünf
Vier wird nur ausgeführt, wenn eine
Exception auftritt.
Verschachtelungen:
finally-except
Delphi-Quellcode:
...
WriteLn('
Null');
try
try
WriteLn('
Eins');
WriteLn(StrToInt('
Zwei'));
WriteLn('
Drei');
finally
WriteLn('
Vier');
end;
// hier wird die Exception nochmal geworfen (analog raise)
except
WriteLn('
Fünf');
end;
WriteLn('
Sechs');
...
Gibt Ausgabe:
Code:
...
Null
Eins
Vier
Fünf
Sechs
...
except-finally
Delphi-Quellcode:
...
WriteLn('
Null');
try
WriteLn('
Eins');
try
WriteLn(StrToInt('
Zwei'));
except
WriteLn('
Drei');
end;
// Exception abgefangen
WriteLn('
Vier');
finally
WriteLn('
Fünf');
end;
// hier wird die Exception nochmal geworfen (analog raise), falls eine aufgetreten ist und nicht abgefangen wurde.
WriteLn('
Sechs');
...
Gibt Ausgabe:
Code:
...
Null
Eins
Drei
Vier
Fünf
Sechs
Warum das ganze?
try ... finally wird dazu verwendet, sicherzustellen, dass bestimmter Code auch nach einer
Exception ausgeführt wird. Z.B. das Freigaben eines Objekts.
Der Code zwischen finally und end wird also auf jeden Fall ausgeführt, egal ob ein Fehler auftritt oder nicht.
Delphi-Quellcode:
...
MyObject := TMyObject.Create
try
MyObject.DoSomething;
finally
MyObject.Free;
end;
...
try except wird dazu verwendet Fehler abzufangen und darauf zu reagieren.
Der Code zwischen except und end wird nur im Fehlerfall ausgeführt
Delphi-Quellcode:
...
try
i := StrToInt(s);
except
WriteLn('
Es ist ein Fehler aufgetreten. s ist kein Integer');
end;
...
// oder
try
i := StrToInt(s);
except
on E:
Exception do
begin
WriteLn('
Es ist ein Fehler aufgetreten.');
WriteLn('
Fehlermeldung: ', E.
Message);
end;
end;
...
Besser ist es aber bei "erwarteten" Fehlern nur die entsprechende Fehlerklasse abzufangen.
(Anmerkung: Noch besser wäre es natürlich den erwarteten Fehler zu vermeiden, statt per
Exception abzufangen.)
Delphi-Quellcode:
...
try
i := StrToInt(s);
except
on E: EConvertError
do
begin
WriteLn('
Es ist ein Fehler aufgetreten.');
WriteLn('
Fehlermeldung: s ist keine Ganzzahl');
end;
on E: EAnderErwarteterFehler
do WriteLn('
Andere Fehlermeldung');
end;
// Hier wird dann für jeden anderen Fehler außer EConvertError und EErwarteterFehler eine Exception geworfen.
...
Es gibt aber auch ein paar Fallstricker bei verschachtelten Exceptions.
Z.B. werden bei manchen Exceptions die objekte, in denen der Fehler aufgetreten ist referenziert.
Wenn hier in einem finally das objekt freigegeben wird, gibt's beim Zugriff auf die Referenz im
Exception Objekt evtl eine allgemeine Schutzverletzung.
Zu dem Thema gibt es noch viel zu Schreiben: globales
Exception handling, Unterstützung durch z.B. jcl, MAD-Except, ...