Grundkurs i C-Sharp - Undantagshantering
Förord
När man skriver ett program är det alltid fel hanteringen som är den viktigaste. Den har till uppgift att se till att användarens upplevelse av programmet fortlöper så smärtfritt som möjligt. Det är därför inte svårt att förstå varför det oftast är större delen av ett program som är ägnat att fånga och hantera den uppsjö av fel som kan inträffa. I C-Sharp bygger all felhantering på att man kastar så kallade undantag (exceptions) som det är upptill programmeraren att fånga och hantera om han vill, vilket oftast är lämpligt. Det finns en stor samling standard undantag som man kan använda och kasta om man vill och man kan även skapa egna typer av undantag som är anpassade för de klasser som man skriver. Samtliga undantag är subklasser till en klass vid namnet Exception som finns i namnrymden System.Innehåll
»»
»
»
»
»
»
Relaterade artiklar
» Grundkurs i C-Sharp - Arv» Grundkurs i C-Sharp - Gränssnitt
» Grundkurs i C-Sharp - Introduktion
» Grundkurs i C-Sharp - Namnrymder
» Grundkurs i C-Sharp - Polymorphism
» Grundkurs i C-Sharp - Statiska medlemmar
» Grundkurs i C-Sharp - Strukturer
» Grundkurs i C-Sharp - Åtkomstmodifiering
» Grundkurs i C-Sharp - Överlastning
Throw
När ett fel uppstår använder man sig av nyckelordet throw [1] för att kasta ett undantag och på så sätt signalera ett fel har skett. Låt oss titta på ett exempel som kastar ett undantag av typen Exception för enkelhetens skull.
class FileManager
{
public void Load(string filename)
{
if( File.Exists(filename) )
{
// Öppna filen
}
else
throw new Exception();
}
}
Här har vi skapat en klass med namnet FileManager som har en metod för att läsa in en fil. Metoden använder sig av den statiska metoden Exists i klassen File (som förövrigt finns i namnrymden System.IO) för att undersöka om det var en giltig sökväg till filen. Om filen finns genomför den lite kod för att öppna den annars kastar den ett nytt undantag av typen Exception för att indikera att det misslyckades.
Det kan även vara lämpligt att skicka med en text som säger vad det var för fel som uppstod, för det är inte så informativt att bara få reda på att det skede ett fel utan även vad som gick fel. Klassen Exception kan även ta en textsträng som parameter så vi kan anpassa programmet för att använda sig av denna.
class FileManager
{
public void Load(string filename)
{
if( File.Exists(filename) )
{
// Öppna filen
}
else
throw new Exception(“Filen du angav finns inte.”);
}
}
Om du har programmerat i Java tidigare har du säkert lagt märket till att man inte behöver deklarera i metoden vilka undantag den kan kasta. Detta är något som diskuterats ganska mycket på de allmänna nyhetsgrupperna och forumen och jag delar den allmänna uppfattningen om att det inte finns någon vits att tvinga det eftersom Java utvecklare oftast kringgår detta med en enkel metod för att fånga upp alla undantag som kastas och på så sätt missar tanken bakom det hela.
Try och Catch
Att kunna kasta undantag när fel uppstår är bara en halva av två som behövs för att kunna implementera felhantering. Vi behöver även ett sätt att kunna fånga upp de olika undantagen som kastas av programmet. I C-Sharp använder man sig av en så kallad prova och fånga metod [2] . När man vet vilket eller vilka undantag som ett anrop till en klass kan resultera i (det skall alltid framgå ur dokumentationen) och man väljer att skriva kod för felhantering i sitt program kan man fånga undantag på följande sätt.
FileManager f = new FileManager();
try
{
f.Load(“C:\Program Files\MyProgram\Settings.xml”);
}
catch(Exception e)
{
Console.WriteLine( e.toString() );
}
I ovanstående kod säger vi att vi vill prova (try) att anropa en metod (Load) som kan resultera i ett fler och att vi vill fånga (catch) alla fel av typen Exception som kastas av koden inne i provsatsen. Som parameter till vår sats för att fånga och hantera fel säger vi inte bara den skall fånga undantag av typen Exception utan även att den skall stoppa in dessa fel i ett objekt med namnet e. Detta objekt använder vi sen för att skriva ut det felmeddelande som skickades med undantaget.
Ibland kan ett anrop resultera i ett av flera olika möjliga undantag kastas och man vill då givetvis kunna fånga och hantera samtliga typer av fel. Låt oss föreställa oss att vi har modifierat vår Load metod i klassen FileManager så att den kastar två olika typer av undantag, nämligen FileNotFoundException om filen inte finns och FileLoadException om filen hittades man den gick inte att öppna.
FileManager f = new FileManager();
try
{
f.Load(“C:\Program Files\MyProgram\Settings.xml”);
}
catch(FileNotFoundException e)
{
Console.WriteLine( e.toString() );
}
catch(FileLoadException e)
{
Console.WriteLine( e.toString() );
}
Som du ser är det bara att lägga till ytterligare rutiner för att fånga (catch) de olika felen som kan uppstå.
Finally
Det finns en utökad form av try/catch som används när man vill att gemensam kod skall köras vare sig ett fel uppstod eller inte. Denna form heter try / catch / finally och som namnet säger så finns dett ytterligare ett nyckelord nämligen finally [3] som man kan använda för just detta.Om vi fortsätter att använda vår FileManager klass så kan vi använda Finally delen för att rensa upp eventuella objekt som har deklarerats men som inte behövs när ett fel uppstod. Som du kan se skapade vi objektet f av typen FileManager utanför vår kod för felhantering. Skulle ett fel uppstå kan det vara lämpligt att frigöra detta objektet och får tillbaka lite minne.
FileManager f = new FileManager();
try
{
f.Load(“C:\Program Files\MyProgram\Settings.xml”);
}
catch(FileNotFoundException e)
{
Console.WriteLine( e.toString() );
}
catch(FileLoadException e)
{
Console.WriteLine( e.toString() );
}
finally
{
if ( f != null )
f.Dispose();
}
Anpassade fel
När man skriver sina program så vill man oftast skapa sina egna fel som man kan kasta när något inte fungerar som det skall. Om du är intresserad av att göra detta så rekommenderar jag sig att läsa min artikel om ärvning och sen ta en titt på dokumentationen för klassen Exception [4] och sen skapa en subklass till den. Ta även en titt på [5] för ett exempel på hur man skapar subklasser till klassen Exception.
Rekommenderad läsning
[1] [2]
[3]
[4]
[5]
0 Kommentarer