Embarcadero Delphi
Användning av försök, utom och slutligen
Sök…
Syntax
Försök med undantag: försök [uttalanden] förutom [[[på E: ExceptionType do statement]] [else statement] | [uttalanden] slut;
Försök äntligen: försök [uttalanden] slutligen [uttalanden] slut;
Enkelt försök .. slutligt exempel för att undvika minnesläckor
Använd try - finally att undvika läckande resurser (t.ex. minne) om ett undantag inträffar under körning.
Proceduren nedan sparar en sträng i en fil och förhindrar att TStringList läcker.
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;
Oavsett om ett undantag inträffar vid lagring av filen kommer SL att frigöras. Alla undantag går till den som ringer.
Undantagssäker återkomst av ett nytt objekt
När en funktion returnerar ett objekt (i motsats till att använda ett som har skickats in av den som ringer), var noga med att ett undantag inte får objektet att läcka.
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;
Naiva programmerare kan försöka fånga alla undantagstyper och återlämna nil från en sådan funktion, men det är bara ett speciellt fall av den allmänna avskräckta praxisen att fånga alla undantagstyper utan att hantera dem.
Försök att äntligen kapsla in i try-utom
Ett try - finally block kan kapslas in i ett try - except block.
try
AcquireResources;
try
UseResource;
finally
ReleaseResource;
end;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
Om ett undantag inträffar i UseResource kommer ReleaseResource att ReleaseResource till ReleaseResource . Om undantaget är en EResourceUsageError , kommer exekveringen att hoppa till undantagshanteraren och anropa HandleResourceErrors . Undantag av någon annan typ kommer att hoppa över undantagshanteraren ovan och bubbla upp till nästa try - except blockera samtalstaket.
Undantag i AcquireResource eller ReleaseResource orsakar exekveringen att gå till undantag handler, hoppa över finally blocket, antingen på grund av motsvarande try blocket inte har angetts ännu eller på grund av finally blocket har redan matats in.
Försök-utom kapslade in try-slutligen
Ett try - except block kan kapslas in i ett try - finally blockera.
AcquireResource;
try
UseResource1;
try
UseResource2;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource3;
finally
ReleaseResource;
end;
Om en EResourceUsageError inträffar i UseResource2 , kommer exekveringen att hoppa till undantagshanteraren och ringa HandleResourceError . Undantaget kommer att betraktas som hanterat, så körning fortsätter till UseResource3 och sedan ReleaseResource .
Om ett undantag av någon annan typ förekommer i UseResource2 , då undantag handler show här inte kommer att gälla, så utförandet kommer att hoppa över UseResource3 samtalet och gå direkt till finally blocket, där ReleaseResource kommer att kallas. Därefter hoppas exekveringen till nästa tillämpliga undantagshanterare när undantaget bubblar upp samlingsstacken.
Om ett undantag inträffar i något annat samtal i exemplet HandleResourceErrors kommer HandleResourceErrors inte att HandleResourceErrors . Detta beror på att inget av de andra samtalen inträffar i try som motsvarar den undantagshanteraren.
Försök slutligen med två eller flera objekt
Object1 := nil;
Object2 := nil;
try
Object1 := TMyObject.Create;
Object2 := TMyObject.Create;
finally
Object1.Free;
Object2.Free;
end;
Om du inte initialiserar objekten med nil utanför try-finally blocket, om ett av dem inte skapas, kommer en AV att inträffa på det slutliga blocket, eftersom objektet inte kommer att vara noll (eftersom det inte initialiserades) och kommer att orsaka ett undantag.
Metoden Free kontrollerar om objektet är noll, så att initiera båda objekten med nil undviker fel när de frigörs om de inte skapades.