Examinați cum să creați și să generați excepții în C#
- 16 minute
.NET furnizează o ierarhie de clase de excepții care derivă din clasa de System.Exception bază. Aplicațiile C# pot crea și genera excepții de orice tip de excepție. Dezvoltatorii pot, de asemenea, să particularizeze obiecte de excepție cu informații specifice aplicației, atribuind valori de proprietate.
Notă
Acest modul se concentrează pe crearea și generarea de excepții și particularizarea obiectelor de excepție. Crearea de clase de excepții particularizate se află în afara domeniului acestui modul.
Crearea unui obiect excepție
Crearea și legarea excepțiilor din cod reprezintă un aspect important al programării C#. Capacitatea de a genera o excepție ca răspuns la o anumită condiție, problemă sau eroare vă ajută să asigurați stabilitatea aplicației.
Tipul de excepție pe care îl creați depinde de problema de codificare și ar trebui să corespundă cu scopul intenționat al excepției cât mai îndeaproape posibil.
De exemplu, să presupunem că creați o metodă denumită GraphData care efectuează analize de date. Metoda primește o matrice de date ca parametru de intrare. Metoda așteaptă ca datele de intrare să fie într-o anumită zonă. Dacă metoda primește date care se află în afara intervalului așteptat, aceasta creează și generează o excepție de tip ArgumentException. Excepția va fi gestionată undeva în josul stivei de apeluri de către codul responsabil pentru furnizarea datelor.
Iată câteva tipuri comune de excepții pe care le puteți utiliza atunci când creați o excepție:
-
ArgumentExceptionsauArgumentNullException: Utilizați aceste tipuri de excepții atunci când se apelează o metodă sau un constructor cu o valoare de argument nevalidă sau o referință nulă. -
InvalidOperationException: Utilizați acest tip de excepție atunci când condițiile de funcționare ale unei metode nu acceptă finalizarea cu succes a unui anumit apel de metodă. -
NotSupportedException: Utilizați acest tip de excepție atunci când o operațiune sau o caracteristică nu este acceptată. -
IOException: Utilizați acest tip de excepție atunci când o operațiune de intrare/ieșire nu reușește. -
FormatException: Utilizați acest tip de excepție atunci când formatul unui șir sau date este incorect.
Cuvântul new cheie este utilizat pentru a crea o instanță a unei excepții. De exemplu, puteți crea o instanță a tipului ArgumentException de excepție după cum urmează:
ArgumentException invalidArgumentException = new ArgumentException();
Configurarea și aruncarea excepțiilor particularizate
Procesul de generare a unui obiect excepție implică crearea unei instanțe a unei clase derivate de excepție, opțional configurarea proprietăților excepției, apoi aruncarea obiectului throw utilizând cuvântul cheie.
Adesea este util să particularizați o excepție cu informațiile contextuale înainte de a fi lansată. Puteți furniza informații specifice aplicației într-un obiect excepție configurând proprietățile sale. De exemplu, următorul cod creează un obiect excepție denumit invalidArgumentException cu o proprietate particularizată Message , apoi generează excepția:
ArgumentException invalidArgumentException = new ArgumentException("ArgumentException: The 'GraphData' method received data outside the expected range.");
throw invalidArgumentException;
Notă
Proprietatea Message unei excepții este doar în citire. Prin urmare, trebuie setată o proprietate particularizată Message la instanțierea obiectului.
Atunci când particularizați un obiect excepție, este important să furnizați mesaje de eroare clare care descriu problema și cum să o rezolvați. De asemenea, puteți include informații suplimentare, cum ar fi trasări de stivă și coduri de eroare, pentru a-i ajuta pe utilizatori să corecteze problema.
De asemenea, un obiect excepție poate fi creat direct într-o throw instrucțiune. De exemplu:
throw new FormatException("FormatException: Calculations in process XYZ have been cancelled due to invalid data format.");
Printre considerațiile de reținut atunci când generați o excepție se numără:
- Proprietatea
Messagear trebui să explice motivul excepției. Totuși, informațiile sensibile sau care reprezintă o problemă de securitate nu ar trebui să fie introduse în textul mesajului. - Proprietatea
StackTraceeste utilizată adesea pentru a urmări originea excepției. Această proprietate șir conține numele metodelor din stiva de apeluri curentă, împreună cu numele de fișier și numărul de linie din fiecare metodă asociată cu excepția. UnStackTraceobiect este creat automat de modulul runtime lingvistic comun (CLR) din punctul de instrucțiunethrow. Excepțiile trebuie să fie lansate din punctul în care ar trebui să înceapă trasarea stivei.
Când se lansează o excepție
Metodele ar trebui să genereze o excepție ori de câte ori nu își pot finaliza scopul. Excepția lansată ar trebui să se bazeze pe cea mai specifică excepție disponibilă, care corespunde condițiilor de eroare.
Luați în considerare un scenariu în care un dezvoltator lucrează la o aplicație care implementează un proces de afaceri. Procesul de afaceri depinde de intrările utilizatorilor. Dacă intrarea nu corespunde tipului de date așteptat, metoda care implementează procesul de afaceri creează și generează o excepție. Obiectul excepție poate fi configurat cu informații specifice aplicației în valorile proprietății. Următorul exemplu de cod demonstrează scenariul:
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;
}
}
}
În acest exemplu de cod, instrucțiunile de nivel superior apelează BusinessProcess1 metoda, trecând într-o matrice de șir care conține valori introduse de utilizator. Metoda BusinessProcess1 așteaptă valori de intrare ale utilizatorului care pot fi convertite într-un număr întreg. Atunci când metoda întâlnește date cu un format nevalid, creează o instanță a tipului FormatException de excepție utilizând o proprietate particularizată Message . Metoda generează apoi excepția. Excepția este prinsă în instrucțiunile de nivel superior ca obiect denumit ex. Proprietățile obiectului ex sunt examinate înainte de a afișa mesajul de excepție utilizatorului. Mai întâi, codul examinează StackTrace proprietatea pentru a vedea dacă conține "BusinessProcess1". În al doilea rând, obiectul ex excepției este verificat ca fiind de tipul FormatException.
Re-generare excepții
În plus față de adăugarea unei noi excepții, throw se poate utiliza re-aruncarea unei excepții din interiorul unui catch bloc de cod. În acest caz, throw nu ia un operand de excepție.
catch (Exception ex)
{
// handle or partially handle the exception
// ...
// re-throw the original exception object for further handling down the call stack
throw;
}
Atunci când re-generați o excepție, se utilizează obiectul original de excepție, astfel încât să nu pierdeți informații despre excepție. Dacă doriți să creați un obiect excepție nou care încadrează excepția inițială, puteți transmite excepția inițială ca argument constructorului unui obiect excepție nou. De exemplu:
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);
}
Pentru scenariul aplicației "BusinessProcess1", luați în considerare următoarele actualizări:
- Metoda
BusinessProcess1a fost actualizată pentru a include detalii suplimentare.BusinessProcess1acum întâmpină două probleme și trebuie să genereze excepții pentru fiecare problemă. - Instrucțiunile de nivel superior au fost actualizate. Instrucțiunile de nivel superior apelează
OperatingProcedure1acum metoda.OperatingProcedure1apeluriBusinessProcess1într-un bloc detrycod. - Metoda
OperatingProcedure1poate gestiona unul dintre tipurile de excepții și îl poate gestiona parțial pe celălalt. După ce este procesată excepția parțial gestionată,OperatingProcedure1trebuie să re-generați excepția originală.
Următorul exemplu de cod demonstrează scenariul actualizat:
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;
}
}
}
Codul eșantion actualizat produce următoarea ieșire:
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.
Lucruri de evitat atunci când generați excepții
Următoarea listă identifică practicile de evitare atunci când generați excepții:
- Nu utilizați excepții pentru a modifica fluxul unui program ca parte a executării obișnuite. Utilizați excepții pentru a raporta și gestiona condițiile de eroare.
- Excepțiile nu ar trebui returnate ca valoare returnată sau ca parametru în loc să fie lansate.
- Nu aruncați
System.Exception,System.SystemExceptionSystem.NullReferenceException, , sauSystem.IndexOutOfRangeExceptionintenționat din propriul cod sursă. - Nu creați excepții care pot fi lansate în modul de depanare, dar nu și în modul de lansare. Pentru a identifica erorile de rulare în timpul fazei de dezvoltare, utilizați
Debug.Assertîn schimb.
Notă
Metoda Debug.Assert este un instrument pentru prinderea erorilor logice în timpul dezvoltării. În mod implicit, Debug.Assert metoda funcționează doar în compilările de depanare. Puteți utiliza Debug.Assert în sesiuni de depanare pentru a verifica dacă există o condiție care nu ar trebui să apară niciodată. Metoda preia doi parametri: o condiție booleană de verificat și un mesaj de șir opțional de afișat dacă condiția este false.
Debug.Assert nu ar trebui utilizat în locul aruncării unei excepții, o modalitate de a gestiona situații excepționale în timpul executării normale a codului. Ar trebui să utilizați Debug.Assert pentru a captura erori care nu ar trebui să apară niciodată și să utilizați excepții pentru a gestiona erorile care ar putea apărea în timpul executării normale a programului.
Recapitulare
Iată câteva lucruri importante de reținut din această unitate:
- Atunci când creați și generați o excepție, tipul de excepție trebuie să corespundă cu scopul propus al excepției cât mai bine posibil.
- Pentru
throwo excepție, creați o instanță a unei clase derivate de excepție, configurați proprietățile, apoi utilizațithrowcuvântul cheie. - Atunci când creați un obiect excepție, este important să furnizați mesaje de eroare clare și informații suplimentare pentru a-i ajuta pe utilizatori să corecteze problema.
Verificați-vă cunoștințele
Feedback
Această pagină a fost utilă?
Nu
Aveți nevoie de ajutor cu acest subiect?
Doriți să încercați să utilizați Întrebați Microsoft Learn pentru a clarifica sau primi îndrumări privind acest subiect?