Delphi exception handling (afhandelen van uitzonderingen)
Inleiding
Delphi beschikt over een geavanceerd fouten afhandelingssysteem.
In dit paper kijken we hoe e.e.a. geimplementeerd kan worden binnen je applicatie.
Foutenafhandeling binnen Delphi
Het systeem van foutenafhandeling binnen Delphi heeft als voordeel dat programma's
ondanks eventuele
fouten toch kunnen blijven draaien zonder dat het programma crasht.
Het programma kan netjes afsluiten, zodat gegevens opgeslagen kunnen worden.
Wanneer er tijdens de uitvoer van een programma iets fout gaat zal Delphi een uitzondering
genereren.
Deze uitzondering kan in de betreffende code opgelost worden. (Je moet dit wel zelf
programmeren uiteraard)
Als de programmacode niets doet zal de fout doorgespeeld worden aan de aanroepende
code, net zolang totdat
er code is die de fout oplost. Als laatste, als er geen code is die de fout oplost, zal
Delphi zelf de fout melden en trachten
deze op te lossen op een nette manier.
De fout komt als het ware uit het programma omhoog 'drijven'.
Het systeem
De volgende sleutelwoorden behoren tot het foutafhandelingssysteem :
try
except
finally
raise
try geeft het begin van de code aan waar op gechecked wordt.
except geeft het einde van de deze code aan.
finally geeft code aan die ondanks de fout absoluut uitgevoerd moet
worden.
raise geeft de mogelijkheid om zelf een fout te genereren.
Bovenstaande sleutelwoorden worden in twee soorten blokken gebruikt :
function DoDivide (x,y : integer) : Double;
begin
try
Result : x / y;
except //Except blok
on EZeroDivide do //Indien deze fout dan oplossen!
begin
Result := 0,0;
ShowMessage('Deling door nul!');
end;
end;
end;
|
Het try... finally blok :
try
// de code
finally
//Voer uit te voeren code uit, wat er ook gebeurd!
end;
Dit blok garandeert dat de code na finally hoe dan ook uitgevoerd wordt.
Dit blok is vooral belangrijk ten aanzien van het free-en van objecten. (Resource
protection) Door objecten bijv. forms in het
finally gedeelte te free-en wordt voorkomen dat zij onnodig resources gebruiken.
In onderstaand voorbeeld wordt dynamisch een form gecreëerd binnen een Try..finally
block.
procedure TForm1.button1Click(Sender : TObject);
begin
frmShowResult := TfrmShowResult.Create(self);
try //Finally blok
frmShowResult.ShowModal;
Finally
frmShowResult.free;//Free the form
end;
end;
|
Raise exceptions
Raise kan gebruikt worden om de exception te re-raisen. Hiermee kan de exception alsnog
afgehandeld worden.
Tevens kan je met raise zelf exceptions genereren : raise
EDiveByZero.Create ('Deling door nul');
Beide blokken nesten
Beide blokken kunnen genest gebruikt worden.
Onderstaande code is een procedure die de getallen uit twee editboxen van elkaar aftrekt.
De uitkomst mag niet kleiner dan nul zijn, indien de uitkomst kleiner dan nul is moet de
uitkomst nul worden.
Omdat tijdens de uitvoer van de functie de cursor wordt verandert in een zandloper dient
naast het except blok
een finally blok genest worden. Dit om er voor te zorgen dat de cursor weer normaal wordt,
ondanks een optredende fout.
Merk op dat door gebruik te maken van het object E alle soorten fouten afgehandeld kunnen
worden.
E is een object van het type exception en ontvangt de waarde van het gecreëerde exception
object.
Dus ook als er in de edit's letters worden ingevoerd zal onderstaande code dit netjes
afhandelen.
function TForm1.DoeBerekening : Integer;
begin
Try //Finally blok
Try //Except blok
result := StrToInt(Edit1.text) - StrToInt(Edit2.text);
if result < 0 then //raise
raise exception.Create('Uitkomst < 0');
except
on E:exception do //E is object van type exception
begin
result := 0;
showmessage(E.Message);
end;
end;
Finally
Screen.Cursor := crDefault; //Hoe dan ook cursor 'resetten'
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Screen.Cursor := crHourGlass;
lblUitkomst.caption := IntToStr(Doeberekening);
end;
|
Het maken van eigen exceptions
Exceptions zijn eenvoudig zelf te maken :
type
EMijnFout = class ( Exception );
raise EMijnFout.Create ('Sorry mijn fout!'):
Einde exceptions.