Embarcadero Delphi
Gebruik van proberen, behalve en tot slot
Zoeken…
Syntaxis
Try-except: try [statements] behalve [[[on E: ExceptionType do statement]] [else statement] | [verklaringen] einde;
Probeer-eindelijk: probeer [statements] eindelijk [statements] einde;
Eenvoudig proberen ... tot slot een voorbeeld om geheugenlekken te voorkomen
Gebruik try
- finally
om lekkende bronnen (zoals geheugen) te voorkomen voor het geval er een uitzondering optreedt tijdens de uitvoering.
De onderstaande procedure slaat een string in een bestand op en voorkomt dat de TStringList
lekt.
procedure SaveStringToFile(const aFilename: TFilename; const aString: string);
var
SL: TStringList;
begin
SL := TStringList.Create; // call outside the try
try
SL.Text := aString;
SL.SaveToFile(aFilename);
finally
SL.Free // will be called no matter what happens above
end;
end;
Ongeacht of er een uitzondering optreedt tijdens het opslaan van het bestand, wordt SL
vrijgegeven. Elke uitzondering gaat naar de beller.
Uitzonderlijk veilige terugkeer van een nieuw object
Wanneer een functie een object retourneert (in tegenstelling tot het gebruik van een object dat door de beller is doorgegeven), moet u oppassen dat een uitzondering niet tot gevolg heeft dat het object lekt.
function MakeStrings: TStrings;
begin
// Create a new object before entering the try-block.
Result := TStringList.Create;
try
// Execute code that uses the new object and prepares it for the caller.
Result.Add('One');
MightThrow;
except
// If execution reaches this point, then an exception has occurred. We cannot
// know how to handle all possible exceptions, so we merely clean up the resources
// allocated by this function and then re-raise the exception so the caller can
// choose what to do with it.
Result.Free;
raise;
end;
// If execution reaches this point, then no exception has occurred, so the
// function will return Result normally.
end;
Naïeve programmeurs proberen misschien alle uitzonderingstypen te vangen en nil
uit een dergelijke functie, maar dat is slechts een speciaal geval van de algemene ontmoedigde praktijk om alle uitzonderingstypen te vangen zonder ze te hanteren.
Probeer-eindelijk genest in probeer-behalve
Een try
- finally
blok kan worden genest in een try
- except
blok.
try
AcquireResources;
try
UseResource;
finally
ReleaseResource;
end;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
Als er een uitzondering optreedt in UseResource
, wordt de uitvoering naar ReleaseResource
. Als de uitzondering een EResourceUsageError
, springt de uitvoering naar de uitzonderingshandler en roept HandleResourceErrors
. Uitzonderingen van een ander type slaan de uitzonderingshandler hierboven over en borrelen door naar de volgende try
- except
de oproepstack blokkeren.
Uitzonderingen in AcquireResource
of ReleaseResource
zorgen ervoor dat de uitvoering naar de uitzonderingshandler gaat en het finally
blok overslaat, hetzij omdat het bijbehorende try
blok nog niet is ingevoerd of omdat het finally
blok al is ingevoerd.
Probeer-behalve genest in try-eindelijk
Een try
- except
blok mag genest worden in een try
- finally
blok.
AcquireResource;
try
UseResource1;
try
UseResource2;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource3;
finally
ReleaseResource;
end;
Als een EResourceUsageError
optreedt in UseResource2
, gaat de uitvoering naar de uitzonderingshandler en wordt HandleResourceError
. De uitzondering wordt als afgehandeld beschouwd, zodat de uitvoering doorgaat naar UseResource3
en vervolgens ReleaseResource
.
Als er een uitzondering van een ander type komt voor in UseResource2
, dan is de uitzondering handler voorstelling zal hier niet van toepassing, zodat de uitvoering zal springen over de UseResource3
gesprek en ga direct naar het finally
blok waar ReleaseResource
zal worden genoemd. Daarna zal de uitvoering naar de volgende toepasselijke uitzonderingshandler springen als de uitzondering de call-stack oproept.
Als in het bovenstaande voorbeeld een uitzondering optreedt in een andere aanroep, wordt HandleResourceErrors
niet aangeroepen. Dit komt omdat geen van de andere aanroepen plaatsvinden binnen het try
blok dat overeenkomt met die uitzonderingshandler.
Probeer het eindelijk met 2 of meer objecten
Object1 := nil;
Object2 := nil;
try
Object1 := TMyObject.Create;
Object2 := TMyObject.Create;
finally
Object1.Free;
Object2.Free;
end;
Als u de objecten niet met nil
buiten het try-finally
blok initialiseert, als een van hen niet wordt gemaakt, zal er een AV op het slot-blok optreden, omdat het object niet nul zal zijn (omdat het niet was geïnitialiseerd) en zal een uitzondering veroorzaken.
De Free
methode controleert of het object nul is, dus door beide objecten met nil
initialiseren, voorkomt u fouten bij het vrijmaken ervan als ze niet zijn gemaakt.