Øvelse – fange bestemte undtagelsestyper
Tidligere i dette modul har du lært, at de undtagelsesobjekter, der er fanget af dit C#-program, er forekomster af en undtagelsesklasse. Generelt vil catch din kode være en af følgende:
- Et undtagelsesobjekt, der er en forekomst af
System.Exceptionbasisklassen. - Et undtagelsesobjekt, der er en forekomst af en undtagelsestype, der nedarver fra basisklassen. Det kan f.eks. være en forekomst af
InvalidCastExceptionklassen.
Undersøg undtagelsesegenskaber
System.Exception er den basisklasse, som alle afledte undtagelsestyper arver fra. Hver undtagelsestype nedarver fra basisklassen via et bestemt klassehierarki. Klassehierarkiet for InvalidCastException er f.eks. som følger:
Object
Exception
SystemException
InvalidCastException
De fleste af de undtagelsesklasser, der arver fra Exception , tilføjer ikke yderligere funktioner. De nedarver simpelthen fra Exception. Hvis du undersøger egenskaberne for Exception klassen, kan du derfor forstå de fleste undtagelser, og hvordan du kan bruge en undtagelse i din kode.
Her er egenskaberne for Exception klassen:
-
Data: Egenskaben
Dataindeholder vilkårlige data i nøgleværdipar. -
HelpLink: Egenskaben
HelpLinkkan bruges til at indeholde en URL-adresse (eller URN) til en Hjælp-fil, der indeholder omfattende oplysninger om årsagen til en undtagelse. -
HResult: Egenskaben
HResultkan bruges til at få adgang til en kodet numerisk værdi, der er tildelt til en bestemt undtagelse. -
InnerException: Egenskaben
InnerExceptionkan bruges til at oprette og bevare en række undtagelser under håndtering af undtagelser. -
Meddelelse: Egenskaben
Messageindeholder oplysninger om årsagen til en undtagelse. -
Kilde: Egenskaben
Sourcekan bruges til at få adgang til navnet på det program eller det objekt, der forårsager fejlen. -
StackTrace: Egenskaben
StackTraceindeholder en staksporing, der kan bruges til at bestemme, hvor der opstod en fejl. -
TargetSite: Egenskaben
TargetSitekan bruges til at hente den metode, der udløser den aktuelle undtagelse.
Det er okay, hvis du føler dig lidt overvældet af denne undersøgelse af undtagelsesegenskaber, basisklasser og arv. Bare rolig, det er nemmere at fange undtagelser i din kode og få adgang til en undtagelses egenskaber end at forklare, hvordan undtagelser og undtagelsesegenskaber fungerer.
Seddel
I dette modul skal du fokusere på at bruge en undtagelses meddelelsesegenskab til at rapportere undtagelsen i programmets brugergrænseflade.
Få adgang til egenskaberne for et undtagelsesobjekt
Nu, hvor du forstår undtagelsesobjekter og deres egenskaber, er det tid til at begynde at kode.
Opdater din Program.cs-fil på følgende måde:
try { Process1(); } catch { Console.WriteLine("An exception has occurred"); } Console.WriteLine("Exit program"); static void Process1() { try { WriteMessage(); } catch { Console.WriteLine("Exception caught in Process1"); } } static void WriteMessage() { double float1 = 3000.0; double float2 = 0.0; int number1 = 3000; int number2 = 0; Console.WriteLine(float1 / float2); Console.WriteLine(number1 / number2); }Brug et øjeblik på at gennemse koden.
Dette er den samme kode, som du så i det forrige undermodul (løsningskoden for udfordringsaktiviteten). Du ved, at der udløses en undtagelse under
WriteMessagemetoden . Du ved også, at undtagelsen er fanget iProcess1metoden . Du skal bruge denne kode til at undersøge undtagelsesobjekter og specifikke undtagelsestyper.Opdater metoden
Process1på følgende måde:static void Process1() { try { WriteMessage(); } catch (Exception ex) { Console.WriteLine($"Exception caught in Process1: {ex.Message}"); } }Brug et øjeblik på at undersøge dine opdateringer.
Bemærk, at den opdaterede
catchdelsætning fanger en forekomst afExceptionklassen i et objekt med navnetex. Bemærk også, at dinConsole.WriteLine()metode brugerextil at få adgang til objektetsMessageegenskab og vise fejlmeddelelsen i konsollen.Selvom delsætningen
catchkan bruges uden argumenter, anbefales denne fremgangsmåde ikke. Hvis du ikke angiver et argument, registreres alle undtagelsestyper, og du kan ikke afgrænse mellem dem.Generelt bør du kun fange de undtagelser, som din kode ved, hvordan du gendanner fra. Derfor skal din
catchdelsætning angive et objektargument, der er afledt afSystem.Exception. Undtagelsestypen skal være så specifik som muligt. Dette hjælper med at undgå at fange undtagelser, som din undtagelseshandler ikke kan løse. Du skal opdatere din kode for at fange en bestemt undtagelsestype senere i denne øvelse.Vælg Gemi menuen Filer .
Angiv pausepunkt på følgende kodelinje:
Console.WriteLine($"Exception caught in Process1: {ex.Message}");Vælg Start fejlfinding i menuen Kør
Kodeudførelsen skal afbrydes midlertidigt ved pausepunktet.
Hold musemarkøren over
ex.Bemærk, at IntelliSense viser de samme undtagelsesegenskaber, som du undersøgte tidligere.
Brug et minut på at undersøge de oplysninger, der beskriver undtagelsesobjektet
ex.Bemærk, at undtagelsen er en
System.DivideByZeroExceptionundtagelsestype, og at egenskabenMessageer angivet tilAttempted to divide by zero..Bemærk, at
StackTraceegenskaben rapporterer metoden og linjenummeret, hvor fejlen opstod, sammen med sekvensen af metodekald (og linjenumre), der førte til fejlen.Vælg Fortsætpå værktøjslinjen Fejlfinding.
Brug et minut på at undersøge konsoloutputtet.
Bemærk, at undtagelsens
Messageegenskab er inkluderet i det output, der genereres af dit program:∞ Exception caught in Process1: Attempted to divide by zero. Exit program
Fange en bestemt undtagelsestype
Nu, hvor du ved, hvilken undtagelsestype der skal registreres, kan du opdatere din catch delsætning for at håndtere den specifikke undtagelsestype.
Opdater metoden
Process1på følgende måde:static void Process1() { try { WriteMessage(); } catch (DivideByZeroException ex) { Console.WriteLine($"Exception caught in Process1: {ex.Message}"); } }Gem din kode, og start derefter en fejlfindingssession.
Bemærk, at dit opdaterede program rapporterer de samme meddelelser til konsollen.
Selvom de rapporterede meddelelser er de samme, er der en vigtig forskel. Din
Process1metode fanger kun undtagelser af den specifikke type, den er klar til at håndtere.Hvis du vil generere en anden undtagelsestype, skal du
WriteMessageopdatere metoden på følgende måde:static void WriteMessage() { double float1 = 3000.0; double float2 = 0.0; int number1 = 3000; int number2 = 0; byte smallNumber; Console.WriteLine(float1 / float2); // Console.WriteLine(number1 / number2); checked { smallNumber = (byte)number1; } }Bemærk brugen af sætningen
checked.Når du udfører beregninger af integraltyper, der tildeler værdien af én integraltype til en anden integraltype, afhænger resultatet af konteksten for kontrol af overløb. I en
checkedkontekst lykkes konverteringen, hvis kildeværdien er inden for intervallet for destinationstypen. Ellers udløses enOverflowException. I en kontekst, der ikke er markeret, lykkes konverteringen altid og fortsætter på følgende måde:Hvis kildetypen er større end destinationstypen, afkortes kildeværdien ved at fjerne dens "ekstra" vigtigste bit. Resultatet behandles derefter som en værdi af destinationstypen.
Hvis kildetypen er mindre end destinationstypen, er kildeværdien enten sign-extended eller zero-extended, så den har samme størrelse som destinationstypen. Sign-extension bruges, hvis kildetypen er signeret. zero-extension bruges, hvis kildetypen ikke er signeret. Resultatet behandles derefter som en værdi af destinationstypen.
Hvis kildetypen har samme størrelse som destinationstypen, behandles kildeværdien som en værdi af destinationstypen.
Seddel
Beregninger af integraltyper, der ikke findes i en
checkedkodeblok, behandles, som om de er inde i enuncheckedkodeblok.Gem din kode, og start derefter en fejlfindingssession.
Bemærk, at en ny undtagelsestype fanges af delsætningen
catchi sætningerne på øverste niveau i stedet for iProcess1metoden .Programmet udskriver følgende meddelelser i konsollen:
∞ An exception has occurred Exit programSeddel
Blokken
catchiProcess1udføres ikke. Dette er den ønskede funktionsmåde. Du skal kun registrere de undtagelser, som din kode er klar til at håndtere.
Fange flere undtagelser i en kodeblok
På dette tidspunkt undrer du dig måske over, hvad der sker, når der opstår flere undtagelser i en enkelt kodeblok. Vil din kode catch hver undtagelse, som de opstår?
Opdater metoden
WriteMessagepå følgende måde:static void WriteMessage() { double float1 = 3000.0; double float2 = 0.0; int number1 = 3000; int number2 = 0; byte smallNumber; Console.WriteLine(float1 / float2); Console.WriteLine(number1 / number2); checked { smallNumber = (byte)number1; } }Angiv pausepunkt i metoden
WriteMessage()på følgende kodelinje:Console.WriteLine(float1 / float2);Gem din kode, og start derefter en fejlfindingssession.
Gennemgå din kode én linje ad gangen, og læg mærke til, hvad der sker, når din kode håndterer den første undtagelse.
Når den første undtagelse opstår, overføres kontrolelementet til den første
catchdelsætning, der kan håndtere undtagelsen. Den kode, der genererer den anden undtagelse, nås aldrig. Det betyder, at noget af din kode aldrig udføres. Dette kan føre til alvorlige problemer.Brug et øjeblik på at overveje, hvordan du kan administrere flere undtagelser, og hvornår/hvorfor du ikke ønsker, at din kode skal administrere flere undtagelser.
Du har tidligere i dette modul lært, at undtagelser skal fanges så tæt på, hvor de forekommer som muligt. Med dette in mente kan du vælge at opdatere
WriteMessagemetoden for at fange undtagelser ved hjælp af sin egentry-catch. For eksempel:static void WriteMessage() { double float1 = 3000.0; double float2 = 0.0; int number1 = 3000; int number2 = 0; byte smallNumber; try { Console.WriteLine(float1 / float2); Console.WriteLine(number1 / number2); } catch (DivideByZeroException ex) { Console.WriteLine($"Exception caught in WriteMessage: {ex.Message}"); } checked { smallNumber = (byte)number1; } }Du kan også ombryde den kode, der forårsager
OverflowExceptioni en separattry-catchiWriteMessage()metoden .checked { try { smallNumber = (byte)number1; } catch (OverflowException ex) { Console.WriteLine($"Exception caught in WriteMessage: {ex.Message}"); } }Under hvilke betingelser ville det være uønsket at fange efterfølgende undtagelser?
Overvej det, når din metode (eller kodeblok) fuldfører en todelt proces. Antag, at den anden del af processen er afhængig af, at den første del fuldføres. Hvis den første del af processen ikke kan fuldføres, er der ingen grund til at fortsætte til anden del af processen. I dette tilfælde er det ofte bedre at præsentere brugeren for en meddelelse, der forklarer fejlbetingelsen uden at forsøge den resterende del af eller dele af den større proces.
Fange separate undtagelsestyper i en kodeblok
Der er tidspunkter, hvor variationer i dine data kan medføre forskellige typer undtagelser.
Ryd dine pausepunkter, og erstat derefter indholdet af din Program.cs fil med følgende kode:
// inputValues is used to store numeric values entered by a user string[] inputValues = new string[]{"three", "9999999999", "0", "2" }; foreach (string inputValue in inputValues) { int numValue = 0; try { numValue = int.Parse(inputValue); } catch (FormatException) { Console.WriteLine("Invalid readResult. Please enter a valid number."); } catch (OverflowException) { Console.WriteLine("The number you entered is too large or too small."); } catch(Exception ex) { Console.WriteLine(ex.Message); } }Brug et øjeblik på at gennemse denne kode.
Først opretter koden en strengmatrix med navnet
inputValues. Dataene i matrixen er beregnet til at repræsentere de inputværdier, der er angivet af en bruger, som blev bedt om at angive numeriske værdier. Afhængigt af den angivne værdi kan der forekomme forskellige undtagelsestyper.Bemærk, at koden bruger
int.Parsemetoden til at konvertere strengværdierne "input" til heltal. Kodenint.Parseplaceres i entrykodeblok.Angiv et pausepunkt på følgende kodelinje:
int numValue = 0;Gem din kode, og start derefter en fejlfindingssession.
Gennemgå koden én linje ad gangen, og bemærk, at der registreres forskellige undtagelsestyper.
Resumé
Her er et par vigtige ting, du skal huske fra dette undermodul:
- Delsætningen
catchskal konfigureres til at fange en bestemt undtagelsestype. UndtagelsestypenDivideByZeroException. - Der er adgang til egenskaberne for et undtagelsesobjekt i
catchblokken. Du kan f.eks. bruge egenskabenMessagetil at informere programbrugeren om et problem. - Du kan angive to eller flere
catchdelsætninger, når du har brug for at fange mere end én undtagelsestype.