Här är ett intressant faktum: Nej koda är felfri - i själva verket är viss kod full av "fel" med avsikt.
Vad är ett fel i ett program? Ett fel är en felaktigt kodad lösning på ett problem. Sådana är logikfel Det kan leda till felaktiga resultat där allt verkar snyggt sammansatt men resultatet av applikationen är helt oanvändbart. Med logikfel, en Ansökan kanske eller kanske inte slutar fungera.
Undantag kan inkludera fel i din kod där du försöker dela siffror med noll, eller du försöker använda frigjorda minnesblock eller försöka tillhandahålla fel parametrar till en funktion. Men ett undantag i en applikation är inte alltid ett fel.
Undantag och undantagsklassen
Undantag är speciella villkor som kräver särskild hantering. När ett felstypstillstånd inträffar ger programmet ett undantag.
Du (som applikationsskribent) kommer att hantera undantag för att göra din ansökan mer felaktig och att svara på det exceptionella tillståndet.
I de flesta fall kommer du att hitta dig som applikationsförfattare och även biblioteksskribent. Så du skulle behöva veta hur man gör undantag (från ditt bibliotek) och hur man hanterar dem (från din ansökan).
Artikeln om hanteringsfel och undantag ger några grundläggande riktlinjer för hur man ska skydda mot fel med hjälp av try / undantag / slut och försök / slutligen / slutade skyddade block för att svara på eller hantera exceptionella förhållanden.
Ett enkelt försök / utom skyddsblock ser ut:
Prova
ThisFunctionMightRaiseAnException ();
bortsett från// hantera alla undantag som tas upp i ThisFunctionMightRaiseAnException () här
slutet;
ThisFunctionMightRaiseAnException kan ha i sin implementering en kodrad som
höja Undantag. Skapa ('speciellt skick!');
Undantaget är en speciell klass (en av få utan T framför namnet) definierad i sysutils.pas-enheten. SysUtils-enheten definierar flera särskilda syftet med undantag (och skapar därmed en hierarki av undantagsklasser) som ERangeError, EDivByZero, EIntOverflow, etc.
I de flesta fall skulle undantagen som du skulle hantera i det skyddade försöket / förutom blocket inte vara undantaget (bas) klass men av någon speciell undantagsklass definierad i VCL eller i biblioteket du är använder sig av.
Hantera undantag med Try / Except
För att fånga och hantera en undantagstyp skulle du konstruera en "on type_of_exception do" undantagshanterare. "Undantaget gör" ser ganska ut som det klassiska fallet:
Prova
ThisFunctionMightRaiseAnException;
excepton EZeroDivide dobegin// något när du delar med nollslutet;
på EIntOverflow dobegin// något när för stor heltal beräknasslutet;
elsebegin// något när andra undantagstyper tas uppslutet;
slutet;
Observera att den andra delen skulle ta tag i alla (andra) undantag, inklusive de du inte vet något om. Generellt sett ska din kod endast hantera undantag som du faktiskt vet hur du ska hantera och förväntar dig att bli kastad.
Du bör aldrig "äta" ett undantag:
Prova
ThisFunctionMightRaiseAnException;
bortsett från
slutet;
Att äta undantaget innebär att du inte vet hur du ska hantera undantaget eller att du inte vill att användare ska se undantaget eller något däremellan.
När du hanterar undantaget och du behöver mer data från det (det är ju ett exempel på en klass) snarare bara den typ av undantag du kan göra:
Prova
ThisFunctionMightRaiseAnException;
excepton E: Undantag dobegin
ShowMessage (E.Message);
slutet;
slutet;
"E" i "E: Exception" är en tillfällig undantagsvariabel av den typ som anges efter kolumntecknet (i ovanstående exempel basundantagsklassen). Med E kan du läsa (eller skriva) värden till undantagsobjektet, som att få eller ställa in meddelandegenskapen.
Vem frigör undantaget?
Har du lagt märke till hur undantag faktiskt är fall av en klass som faller från undantaget? Nyckelordet höja kastar ett undantagsklassinstans. Det du skapar (undantagsinstansen är ett objekt), du också behöver frigöra. Om du (som biblioteksskribent) skapar en instans, kommer applikationsanvändaren att frigöra den?
Här är Delphi magi: Att hantera ett undantag förstör automatiskt undantagsobjektet. Detta betyder att när du skriver koden i blocket "utom / slut" kommer det att släppa undantagsminnet.
Så vad händer om ThisFunctionMightRaiseAnException faktiskt gör ett undantag och du inte hanterar det (det här är inte detsamma som att "äta" det)?
Vad sägs om när nummer / 0 inte hanteras?
När ett obehandlat undantag kastas i din kod, hanterar Delphi igen magiskt ditt undantag genom att visa feldialogen till användaren. I de flesta fall kommer denna dialog inte att tillhandahålla tillräckligt med data för användaren (och slutligen du) för att förstå orsaken till undantaget.
Detta styrs av Delphis toppnivåmeddelandeslinga där Allt undantag behandlas av det globala applikationsobjektet och dess HandleException-metod.
För att hantera undantag globalt och visa din egen mer användarvänliga dialog kan du skriva kod för TApplicationEvents. Händelsehanterare av OnException.
Observera att det globala applikationsobjektet definieras i formulärsenheten. TApplicationEvents är en komponent som du kan använda för att fånga händelserna i det globala applikationsobjektet.