Hier is een interessant feit: geen code is foutloos - in feite zit sommige code expres vol met "fouten".
Wat is een fout in een toepassing? Een fout is een onjuist gecodeerde oplossing voor een probleem. Dit zijn logische fouten die kunnen leiden tot verkeerde functieresultaten waarbij alles mooi in elkaar lijkt te staan, maar het resultaat van de toepassing volledig onbruikbaar is. Met logische fouten kan een toepassing al dan niet stoppen met werken.
Uitzonderingen kunnen fouten in uw code bevatten waarbij u getallen met nul probeert te delen, of u probeert vrijgemaakte geheugenblokken te gebruiken of probeert een functie verkeerde parameters te geven. Een uitzondering in een toepassing is echter niet altijd een fout.
Uitzonderingen zijn speciale voorwaarden die speciale behandeling vereisen. Wanneer zich een fouttype voordoet, genereert het programma een uitzondering.
U (als de schrijver van de toepassing) behandelt uitzonderingen om uw toepassing foutgevoeliger te maken en te reageren op de uitzonderlijke situatie.
In de meeste gevallen zult u merken dat u de toepassingsschrijver bent en ook de bibliotheekschrijver. Je zou dus moeten weten hoe je uitzonderingen kunt aanvoeren (vanuit je bibliotheek) en hoe je ermee kunt omgaan (vanuit je applicatie).
Het artikel over het omgaan met fouten en uitzonderingen biedt enkele basisrichtlijnen voor het beschermen tegen fouten met behulp van try / behalve / end en try / eindelijk / end beschermde blokken om te reageren op uitzonderlijke omstandigheden.
Een eenvoudige poging / behalve bewakingsblokken ziet eruit als:
proberen
ThisFunctionMightRaiseAnException ();
behalve// omgaan met eventuele uitzonderingen die in ThisFunctionMightRaiseAnException () hier naar voren zijn gebracht
einde;
De ThisFunctionMightRaiseAnException kan bij de uitvoering ervan een coderegel bevatten
raise Exception.Create ('speciale voorwaarde!');
De uitzondering is een speciale klasse (een van de weinige zonder een T voor de naam) gedefinieerd in de eenheid sysutils.pas. De SysUtils-eenheid definieert verschillende afstammelingen van uitzonderingsgevallen (en creëert zo een hiërarchie van uitzonderingsklassen) zoals ERangeError, EDivByZero, EIntOverflow, enz..
In de meeste gevallen zijn de uitzonderingen die u in het beveiligde try / except-blok zou afhandelen niet van de klasse Exception (base) maar van een speciale klasse afstammingsuitzonderingen die is gedefinieerd in de VCL of in de bibliotheek die u gebruikt.
Om een uitzonderingstype te vangen en af te handelen, zou u een uitzonderingshandler "on type_of_exception do" construeren. De "op uitzondering doen" lijkt vrijwel op de klassieke case-uitspraak:
proberen
ThisFunctionMightRaiseAnException;
excepton EZeroDivide dobegin// iets bij delen door nuleinde;
Aan EIntOverflow dobegin// iets als de berekening van een te groot geheel getaleinde;
elsebegin// iets wanneer andere uitzonderingssoorten worden opgeworpeneinde;
einde;
Merk op dat het else-gedeelte alle (andere) uitzonderingen zou bevatten, inclusief die waar u niets van weet. Over het algemeen moet uw code alleen uitzonderingen verwerken die u daadwerkelijk weet te verwerken en waarvan u verwacht dat deze wordt weggegooid.
Je moet ook nooit een uitzondering "eten":
proberen
ThisFunctionMightRaiseAnException;
behalve
einde;
Het eten van de uitzondering betekent dat je niet weet hoe je met de uitzondering moet omgaan of dat je niet wilt dat gebruikers de uitzondering zien of iets er tussenin.
Wanneer u de uitzondering verwerkt en er meer gegevens van nodig hebt (het is tenslotte een instantie van een klasse), in plaats van alleen het type uitzondering dat u kunt doen:
proberen
ThisFunctionMightRaiseAnException;
excepton E: uitzondering dobegin
ShowMessage (e.Message);
einde;
einde;
De "E" in "E: Uitzondering" is een tijdelijke uitzonderingsvariabele van het type dat wordt opgegeven na het kolomteken (in het bovenstaande voorbeeld de basisuitzonderingsklasse). Met E kunt u waarden voor het uitzonderingsobject lezen (of schrijven), zoals de eigenschap Message ophalen of instellen.
Is het je opgevallen hoe uitzonderingen eigenlijk een klasse zijn die afstamt van Uitzondering? Het sleutelwoord raise verhoogt een instantie van een uitzonderingsklasse. Wat u maakt (de uitzonderingsinstantie is een object), moet u ook vrijmaken. Als u (als bibliotheekschrijver) een instantie maakt, zal de toepassingsgebruiker deze vrijmaken?
Dit is de Delphi-magie: het verwerken van een uitzondering vernietigt automatisch het uitzonderingsobject. Dit betekent dat wanneer u de code in het blok "behalve / einde" schrijft, het uitzonderingsgeheugen wordt vrijgegeven.
Dus wat gebeurt er als ThisFunctionMightRaiseAnException daadwerkelijk een uitzondering oproept en u deze niet aanpakt (dit is niet hetzelfde als "eten")?
Wanneer een onverwerkte uitzondering in uw code wordt gegooid, verwerkt Delphi opnieuw op magische wijze uw uitzondering door het foutdialoogvenster aan de gebruiker weer te geven. In de meeste gevallen biedt dit dialoogvenster onvoldoende gegevens voor de gebruiker (en uiteindelijk u) om de oorzaak van de uitzondering te begrijpen.
Dit wordt bestuurd door Delphi's berichtenlus op het hoogste niveau waar allemaal uitzonderingen worden verwerkt door het globale Application-object en de methode HandleException.
Om uitzonderingen wereldwijd af te handelen en uw eigen gebruiksvriendelijker dialoogvenster weer te geven, kunt u code schrijven voor de gebeurtenishandler TApplicationEvents.OnException.
Merk op dat het globale Application-object is gedefinieerd in de Formulieren-eenheid. De TApplicationEvents is een component die u kunt gebruiken om de gebeurtenissen van het globale toepassingsobject te onderscheppen.