Undersøg, hvordan du opretter og udløser undtagelser i C#
- 16 minutter
.NET indeholder et hierarki af undtagelsesklasser, der stammer fra basisklassen System.Exception . C#-programmer kan oprette og udløse undtagelser af enhver undtagelsestype. Udviklere kan også tilpasse undtagelsesobjekter med programspecifikke oplysninger ved at tildele egenskabsværdier.
Bemærk
I dette modul fokuseres der på at oprette og aktivere undtagelser og tilpasse undtagelsesobjekter. Oprettelse af brugerdefinerede undtagelsesklasser er uden for dette moduls område.
Opret et undtagelsesobjekt
Oprettelse og start af undtagelser fra din kode er et vigtigt aspekt ved C#-programmering. Muligheden for at generere en undtagelse som svar på en bestemt betingelse, et bestemt problem eller en bestemt fejl hjælper dig med at sikre stabiliteten af dit program.
Den undtagelsestype, du opretter, afhænger af kodningsproblemet og skal svare til formålet med undtagelsen så tæt som muligt.
Lad os f.eks. antage, at du opretter en metode med navnet GraphData , der udfører dataanalyse. Metoden modtager en datamatrix som en inputparameter. Metoden forventer, at inputdataene er inden for et bestemt område. Hvis metoden modtager data, der er uden for det forventede interval, oprettes og udløses en undtagelse af typen ArgumentException. Undtagelsen håndteres et sted nede i opkaldsstakken af den kode, der er ansvarlig for at levere dataene.
Her er nogle almindelige undtagelsestyper, som du kan bruge, når du opretter en undtagelse:
-
ArgumentExceptionellerArgumentNullException: Brug disse undtagelsestyper, når en metode eller konstruktør kaldes med en ugyldig argumentværdi eller en null-reference. -
InvalidOperationException: Brug denne undtagelsestype, når driftsbetingelserne for en metode ikke understøtter fuldførelsen af et bestemt metodekald. -
NotSupportedException: Brug denne undtagelsestype, når en handling eller funktion ikke understøttes. -
IOException: Brug denne undtagelsestype, når en input-/outputhandling mislykkes. -
FormatException: Brug denne undtagelsestype, når formatet af en streng eller data er forkert.
Nøgleordet new bruges til at oprette en forekomst af en undtagelse. Du kan f.eks. oprette en forekomst af ArgumentException undtagelsestypen på følgende måde:
ArgumentException invalidArgumentException = new ArgumentException();
Konfigurer og kast brugerdefinerede undtagelser
Processen til aktivering af et undtagelsesobjekt omfatter oprettelse af en forekomst af en undtagelsesbaseret klasse, eventuelt konfiguration af egenskaberne for undtagelsen og derefter aktivering af objektet ved hjælp af nøgleordet throw .
Det er ofte nyttigt at tilpasse en undtagelse med kontekstafhængige oplysninger, før de udløses. Du kan angive programspecifikke oplysninger i et undtagelsesobjekt ved at konfigurere dets egenskaber. Følgende kode opretter f.eks. et undtagelsesobjekt med navnet invalidArgumentException med en brugerdefineret Message egenskab og udløser derefter undtagelsen:
ArgumentException invalidArgumentException = new ArgumentException("ArgumentException: The 'GraphData' method received data outside the expected range.");
throw invalidArgumentException;
Bemærk
Egenskaben Message for en undtagelse er skrivebeskyttet. Der skal derfor angives en brugerdefineret Message egenskab, når objektet instantieres.
Når du tilpasser et undtagelsesobjekt, er det vigtigt at angive tydelige fejlmeddelelser, der beskriver problemet, og hvordan du løser det. Du kan også inkludere yderligere oplysninger, f.eks. staksporinger og fejlkoder, for at hjælpe brugerne med at løse problemet.
Et undtagelsesobjekt kan også oprettes direkte i en throw sætning. Eksempler:
throw new FormatException("FormatException: Calculations in process XYZ have been cancelled due to invalid data format.");
Nogle overvejelser, du skal være opmærksom på, når du udløser en undtagelse, omfatter:
- Egenskaben
Messageskal forklare årsagen til undtagelsen. Oplysninger, der er følsomme, eller som repræsenterer et sikkerhedsproblem, bør dog ikke indsættes i meddelelsesteksten. - Egenskaben
StackTracebruges ofte til at spore undtagelsens oprindelse. Denne strengegenskab indeholder navnet på metoderne i den aktuelle kaldstak sammen med filnavnet og linjenummeret i hver metode, der er knyttet til undtagelsen. EtStackTraceobjekt oprettes automatisk af CLR (Common Language Runtime) fra sætningspunktetthrow. Undtagelser skal smides fra det punkt, hvor staksporingen skal starte.
Hvornår skal der udløses en undtagelse?
Metoder skal udløse en undtagelse, når de ikke kan fuldføre deres tilsigtede formål. Den udløste undtagelse skal være baseret på den mest specifikke undtagelse, der er tilgængelig, og som passer til fejlbetingelserne.
Overvej et scenarie, hvor en udvikler arbejder på et program, der implementerer en forretningsproces. Forretningsprocessen er afhængig af brugerinput. Hvis inputtet ikke svarer til den forventede datatype, opretter og udløser den metode, der implementerer forretningsprocessen, en undtagelse. Undtagelsesobjektet kan konfigureres med programspecifikke oplysninger i egenskabsværdierne. I følgende kodeeksempel vises scenariet:
string[][] userEnteredValues = new string[][]
{
new string[] { "1", "two", "3"},
new string[] { "0", "1", "2"}
};
foreach (string[] userEntries in userEnteredValues)
{
try
{
BusinessProcess1(userEntries);
}
catch (Exception ex)
{
if (ex.StackTrace.Contains("BusinessProcess1") && (ex is FormatException))
{
Console.WriteLine(ex.Message);
}
}
}
static void BusinessProcess1(string[] userEntries)
{
int valueEntered;
foreach (string userValue in userEntries)
{
try
{
valueEntered = int.Parse(userValue);
// completes required calculations based on userValue
// ...
}
catch (FormatException)
{
FormatException invalidFormatException = new FormatException("FormatException: User input values in 'BusinessProcess1' must be valid integers");
throw invalidFormatException;
}
}
}
I dette kodeeksempel kalder BusinessProcess1 sætningerne på øverste niveau metoden og overfører en strengmatrix, der indeholder bruger indtastede værdier. Metoden BusinessProcess1 forventer brugerinputværdier, der kan konverteres til et heltal. Når metoden støder på data med et ugyldigt format, oprettes der en forekomst af undtagelsestypen ved hjælp af FormatException en brugerdefineret Message egenskab. Metoden udløser derefter undtagelsen. Undtagelsen er fanget i sætninger på øverste niveau som et objekt med navnet ex. Egenskaberne for ex objektet undersøges, før undtagelsesmeddelelsen vises for brugeren. Først undersøger StackTrace koden egenskaben for at se, om den indeholder "BusinessProcess1". For det andet bekræftes undtagelsesobjektet ex til at være af typen FormatException.
Genaktivering af undtagelser
Ud over at aktivere en ny undtagelse throw , kan bruges re-throw en undtagelse inde fra en catch kodeblok. I dette tilfælde throw tager ikke en undtagelsesoperand.
catch (Exception ex)
{
// handle or partially handle the exception
// ...
// re-throw the original exception object for further handling down the call stack
throw;
}
Når du udløser en undtagelse igen, bruges det oprindelige undtagelsesobjekt, så du ikke mister oplysninger om undtagelsen. Hvis du vil oprette et nyt undtagelsesobjekt, der ombryder den oprindelige undtagelse, kan du overføre den oprindelige undtagelse som et argument til konstruktøren af et nyt undtagelsesobjekt. Eksempler:
catch (Exception ex)
{
// handle or partially handle the exception
// ...
// create a new exception object that wraps the original exception
throw new ApplicationException("An error occurred", ex);
}
I forbindelse med programscenariet "BusinessProcess1" skal du overveje følgende opdateringer:
- Metoden
BusinessProcess1er blevet opdateret, så den indeholder flere oplysninger.BusinessProcess1støder nu på to problemer og skal generere undtagelser for hvert problem. - Sætningerne på øverste niveau er blevet opdateret. Sætninger på øverste niveau kalder
OperatingProcedure1nu metoden .OperatingProcedure1kaldBusinessProcess1i entrykodeblok. - Metoden
OperatingProcedure1kan håndtere en af undtagelsestyperne og delvist håndtere den anden. Når den delvist håndterede undtagelse behandles,OperatingProcedure1skal den oprindelige undtagelse smides igen.
Følgende kodeeksempel viser det opdaterede scenarie:
try
{
OperatingProcedure1();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine("Exiting application.");
}
static void OperatingProcedure1()
{
string[][] userEnteredValues = new string[][]
{
new string[] { "1", "two", "3"},
new string[] { "0", "1", "2"}
};
foreach(string[] userEntries in userEnteredValues)
{
try
{
BusinessProcess1(userEntries);
}
catch (Exception ex)
{
if (ex.StackTrace.Contains("BusinessProcess1"))
{
if (ex is FormatException)
{
Console.WriteLine(ex.Message);
Console.WriteLine("Corrective action taken in OperatingProcedure1");
}
else if (ex is DivideByZeroException)
{
Console.WriteLine(ex.Message);
Console.WriteLine("Partial correction in OperatingProcedure1 - further action required");
// re-throw the original exception
throw;
}
else
{
// create a new exception object that wraps the original exception
throw new ApplicationException("An error occurred - ", ex);
}
}
}
}
}
static void BusinessProcess1(string[] userEntries)
{
int valueEntered;
foreach (string userValue in userEntries)
{
try
{
valueEntered = int.Parse(userValue);
checked
{
int calculatedValue = 4 / valueEntered;
}
}
catch (FormatException)
{
FormatException invalidFormatException = new FormatException("FormatException: User input values in 'BusinessProcess1' must be valid integers");
throw invalidFormatException;
}
catch (DivideByZeroException)
{
DivideByZeroException unexpectedDivideByZeroException = new DivideByZeroException("DivideByZeroException: Calculation in 'BusinessProcess1' encountered an unexpected divide by zero");
throw unexpectedDivideByZeroException;
}
}
}
Den opdaterede eksempelkode giver følgende output:
FormatException: User input values in 'BusinessProcess1' must be valid integers
Corrective action taken in OperatingProcedure1
DivideByZeroException: Calculation in 'BusinessProcess1' encountered an unexpected divide by zero
Partial correction in OperatingProcedure1 - further action required
DivideByZeroException: Calculation in 'BusinessProcess1' encountered an unexpected divide by zero
Exiting application.
Ting, du skal undgå, når der udløses undtagelser
Følgende liste identificerer fremgangsmåder, der skal undgås, når undtagelser aktiveres:
- Brug ikke undtagelser til at ændre flowet for et program som en del af almindelig udførelse. Brug undtagelser til at rapportere og håndtere fejlbetingelser.
- Undtagelser bør ikke returneres som en returværdi eller -parameter i stedet for at blive udløst.
- Kast
System.Exceptionikke ,System.SystemException,System.NullReferenceExceptionellerSystem.IndexOutOfRangeExceptionbevidst fra din egen kildekode. - Opret ikke undtagelser, der kan udløses i fejlfindingstilstand, men ikke udgivelsestilstand. Hvis du vil identificere kørselsfejl i udviklingsfasen, skal du i stedet bruge
Debug.Assert.
Bemærk
Metoden Debug.Assert er et værktøj til at registrere logikfejl under udvikling. Metoden fungerer som standard Debug.Assert kun i fejlfindingsbuilds. Du kan bruge Debug.Assert i fejlfindingssessioner til at kontrollere, om der er en betingelse, der aldrig bør opstå. Metoden kræver to parametre: en boolesk betingelse, der skal kontrolleres, og en valgfri strengmeddelelse, der skal vises, hvis betingelsen er false.
Debug.Assert bør ikke bruges i stedet for at udløse en undtagelse, som er en måde at håndtere ekstraordinære situationer under normal udførelse af din kode. Du bør bruge Debug.Assert til at registrere fejl, der aldrig bør forekomme, og bruge undtagelser til at håndtere fejl, der kan opstå under normal udførelse af dit program.
Resumé
Her er et par vigtige ting, du skal huske fra dette undermodul:
- Når du opretter og udløser en undtagelse, skal undtagelsestypen matche det tilsigtede formål med undtagelsen så tæt som muligt.
- Til
throwen undtagelse skal du oprette en forekomst af en klasse, der er afledt af en undtagelse, konfigurere dens egenskaber og derefter bruge nøgleordetthrow. - Når du opretter et undtagelsesobjekt, er det vigtigt at angive tydelige fejlmeddelelser og yderligere oplysninger for at hjælpe brugerne med at løse problemet.