O excepție este un obiect care încapsulează informații despre o situație anormală. Excepția se folosește pentru a semnala contextul în care apare acea situație deosebită.
Nu trebuie confundat termenul de excepție cu cel de eroare sau „bug”. Excepțiile nu sunt concepute pentru prevenirea bug-urilor. Chiar dacă programatorul elimină toate bug-urile din programul său pot apărea erori pe care el nu le poate preveni:
- încercare de deschidere a unui fișier inexistent
- împărțiri la zero
- etc.
În cazul în care o metodă întâlnește o astfel de excepție, atunci respectiva excepție va trebui „prinsă” în vederea tratării (rezolvării) ei.
În C# se pot arunca ca excepții obiecte de tip System.Exception sau derivate ale lui. Pe lângă ierarhia de excepții pe care limbajul C# o are inclusă, programatorul își poate crea propriile sale tipuri de excepție.
Dintre metodele și proprietățile clasei Exception amintim:
Metodele și proprietățile clasei Exception | Explicații |
public Exception()
public Exception(string) public Exception(string,Exception) |
Sunt constructori
Observăm că o excepție poate conține în interiorul ei o instanță a unei alte excepții |
public virtual string HelpLink {get; set} | Obține sau setează o legătură către fișierul Help asociat excepției, sau către o adresă Web |
public Exception InnerException {get;} | Returnează excepția care este încorporată în excepția curentă |
public virtual string Message {get;} | Obține un mesaj care descrie excepția curentă |
public virtual string Source {get;set} | Obține sau setează numele aplicației sau al obiectului care a cauzat eroarea |
public virtual string StackTrace {get;} | Obține o reprezentare de tip string a apelurilor de metode care au dus la apariția excepției |
public MethodBase TargetSite {get;} | Obține metoda care a aruncat excepția curentă. |
Excepția | Explicații |
ArrayTypeMismatchException | Incompatibilitate între tipul valorii memorate şi tipul tabloului |
DivideByZeroException | Încercare de împărţire la zero |
IndexOutOfRangeException | Indexul tabloului depăşeşte marginile definite |
InvalidCastException | Operatorul cast incorect la execuţie |
OutOfMemoryException | Datorită memoriei insuficiente apelul lui new eşuează |
OverflowException | Depăşire aritmetică |
StackOverflowException | Depăşirea capacităţii (definite) stivei |
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Exceptii1 { class Program { static void Main(string[] args) { try { Console.Write("Introduceti un numar "); int i = int.Parse(Console.ReadLine()); Console.Write("Introduceti inca un numar "); int j = int.Parse(Console.ReadLine()); int x = i / j; } catch (OverflowException e) { Console.WriteLine("Numarul nu este intreg"); //(1) //Console.WriteLine(e); //(2) } /* catch (DivideByZeroException e) { //Console.WriteLine(e); //(3) Console.WriteLine("Exceptia DivideByZero"); //(4) }*/ Console.WriteLine("Programul ruleaza in continuare");//(5) } } }
- Dacă liniile (2) și (3) nu sunt comentate, în urma execuției programului, respectivele linii afișează informații despre excepțiile apărute.
- Liniile (1) și (4) au fost puse pentru a personaliza informațiile referitoare la excepțiile apărute.
- Linia (5) a fost pusă în program pentru a demonstra rularea fără probleme, în cazul în care blocurile catch există.
Pentru a intercepta orice excepții, indiferent de tipul lor se va folosi catch fără parametru. Prin aceasta se va crea o rutină care va intercepta și trata toate excepțiile.
Instrucțiunea throw
Programatorul poate să-și compună modalități proprii de aruncare a erorilor folosind instrucțiunea throw:
throw new NumeExceptie(exceptie);
unde:
NumeExceptie trebuie să fie numele unei clase apropiate de excepția avută în vedere excepție – este un mesaj care apare în cazul în care apare excepția, iar aceasta nu este prinsă cu catch.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Exceptii1 { class Program { static void Main(string[] args) { try //(1) { //(2) Console.Write("Introduceti o cifra "); int i = int.Parse(Console.ReadLine()); if (i < 0 || i > 9) { string exceptie = i + " nu este o cifra"; //(0) throw new ArgumentOutOfRangeException(exceptie); } } //(3) catch (ArgumentOutOfRangeException) //(4) { //(5) Console.WriteLine("Nu este cifra"); //(6) } //(7) Console.WriteLine("Programul ruleaza in continuare"); } } }
- Dacă comentăm liniile (1), (2), (3), (4), (5), (6), (7) și la rularea programului introducem un număr în loc de o cifră, programul se oprește din execuție, iar ca mesaj apare șirul definit de utilizator în linia (0).
- Dacă vom comenta doar liniile aferente blocului catch (4), (5), (6), (7), apare un mesaj de eroare privind faptul că se așteaptă un bloc catch sau finally.
- Dacă nici una dintre liniile programului nu este comentată, la rulare, chiar dacă introduce un număr în loc de o cifră vom obține:
Blocul finally
Limbajul c# permite ca la ieșirea dintr-un bloc try să fie executate obligatoriu, în cazul în care programatorul dorește acest lucru, anumite instrucțiuni. Pentru acest lucru, respectivele instrucțiuni vor fi plasate într-un bloc finally.
Blocul finally este util fie pentru a evita scrierea unor instrucțiuni de mai multe ori, fie pentru a elibera resursele după părăsirea excepției.