Saturday, April 20, 2019 05:06

Excepții

Într-o lume ideală, un program de calculator va executa orice proces intenționt de programator, în modul cum a fost intenționat de programator. Dar, din moment ce nu trăim într-o lume ideală (din păcate), există momente când din cauza greșelii programatorului sau a condițiilor externe, aceste programe vor funcționa defectuos sau nu într-un mod neintenționat, provocând o excepție de la ceea ce ne așteptăm în mod normal .

O excepție este un semnal al software-ului că ceva a perturbat execuția sa obișnuită. De exemplu, am putea să descărcăm un fișier de pe un server. Dar, la jumătatea operației, conexiunea la internet cade și descărcarea nu poate continua. Aceasta este considerată o excepție.

Deși cei mai mulți programatori începători se tem și urăsc excepțiile, experiența ne învață că acestea sunt simple instrumente care ne pot ajuta în detectarea, interacțiunea și corectarea comportamentelor anormale. Când survine o excepție, starea curentă a programului este salvată, execuția este oprită și controlul este transmis unui handler de excepție, dacă există o astfel de componentă în acel context. Excepțiile sunt însoțite de un mesaj de eroare care ne poate ajuta să identificăm ce s-a întâmplat în program. Programatorii spun că o excepție este ridicată (raised) sau aruncată (thrown).

Manipulatorii de excepții sunt mecanisme de programare care permit programului să arunce excepții și să le capteze. În programarea procedurală, metodele și funcțiile returnează de obicei o valoare care poate fi folosită pentru semnalizarea erorilor. În OOP, excepțiile oferă o modalitate mai bună de a face față erorilor și, prin urmare, metodele și funcțiile sunt capabile să arunce și să prindă erorile sau să treacă excepția mai departe către metoda care le-a apelat. Acest lucru permite ca erorile să fie propagate mai mult în stiva de execuție și, prin urmare, să facă codul mult mai flexibil. Un alt lucru bun în cadrul OOP este că excepțiile sunt de fapt clase și astfel putem avea ierarhii de excepții. Încă nu am învățat despre moștenire, dar este suficient să spunem că atunci când se manipulează o excepție (este prinsă), mecanismul de manipulare ar putea captura o întreagă clasă de excepții și nu doar o eroare specială (ca în programarea tradițională procedurală). Cu alte cuvinte, putem capta mai multe tipuri de erori în același timp, într-o manieră centralizată.

Excepțiile sunt obiecte. Acestea descriu eroarea, oferă informații despre aceasta, arată locul din program în care a apărut eroarea și starea programului când a apărut această eroare. Fiecare excepție din .NET conține așa-numita urmă de stivă (stack trace), care oferă informații despre locul exact unde a apărut eroarea. Acest lucru va fi discutat în detaliu mai târziu.

Să luăm un exemplu de cod care va arunca o excepție:

Codul de mai sus va încerca să citească un fișier de pe disc, de la o cale pe care o oferim ca argument pentru funcția care efectuează citirea. Nu am învățat încă despre citirea fișierelor, dar este OK pentru moment. Compilatorul nu se va plânge de erori, deoarece nu există niciuna. Din perspectiva compilatorului, nu există nimic în neregulă cu acest cod. Cu toate acestea, atunci când încercăm să executăm acest program din Windows Explorer, ieșirea va arăta astfel:

Încercarea de a rula codul din Visual Studio va genera aceeași excepție, dar comportamentul va fi diferit. Visual Studio ne va arăta de fapt excepția care apare:

FileNotFoundException

Dacă acest program era o aplicație GUI, comportamentul runtime ar fi diferit din nou. Am obține acest lucru:

și probabil că știm cu toții ce înseamnă acest lucru…

Problema a fost aceea că nu există un fișier la calea pe care am oferit-o metodei respective. Și aceasta generează o excepție. Un alt lucru pe care îl observăm din imaginile de mai sus este faptul că de fapt compilatorul nu ne arată doar linia la care a apărut eroarea, dar și detalii despre eroare, cum ar fi numele și descrierea acesteia. Știm acum că există mai mult de un tip de excepții și că au nume. Cele mai frecvente excepții pe care le veți întâlni în calitate de programator sunt următoarele:

AccessViolationException – Excepția care este aruncată atunci când există o încercare de citire sau scriere a memoriei protejate.
ApplicationException – Excepția care este aruncată atunci când apare o eroare de aplicație non-fatală.
ArgumentException – Excepția care este aruncată atunci când unul dintre argumentele furnizate unei metode este invalid.
ArgumentNullException – Excepția care este aruncată atunci când o referință nulă este transmisă unei metode care nu o acceptă ca argument valid.
ArgumentOutOfRangeException – Excepția care este aruncată atunci când valoarea unui argument este în afara intervalului de valori admisibil definit de metoda apelată.
ArithmeticException – Excepția care este aruncată pentru erori care apar într-o operație de aritmetică sau de conversie.
DivideByZeroException – Excepția care este aruncată atunci când se încearcă divizarea unei valori intregi sau zecimale cu zero.
DllNotFoundException – Excepția care este aruncată când un DLL specificat într-un import DLL nu poate fi găsit.
IndexOutOfRangeException – Excepția care este aruncată atunci când se încearcă accesarea unui element al unui array cu un index care se află în afara limitelor array-ului.
InsufficientMemoryException – Excepția care este aruncată când eșuează o verificare pentru memorie suficientă disponibilă. Această clasă nu poate fi moștenită.
InvalidCastException – Excepția care este aruncată pentru convertirea invalidă sau conversia explicită.
NotFiniteNumberException – Excepția care este aruncată atunci când o valoare în virgulă mobilă este infinit pozitiv, infinit negativ sau nu este un număr (Not-a-Number – NaN).
NullReferenceException – Excepția care este aruncată atunci când există o încercare de dereferențiere a unei referințe de obiect nul.
ObjectDisposedException – Excepția care este aruncată atunci când o operație este efectuată pe un obiect distrus.
OutOfMemoryException – Excepția care este aruncată atunci când nu există suficientă memorie pentru a continua executarea unui program.
OverflowException – Excepția care este aruncată atunci când o operație aritmetică sau de conversie într-un context verificat are ca rezultat o depășire.
StackOverflowException – Excepția care este aruncată atunci când stiva de execuție „depășește”, deoarece conține prea multe apeluri metodă imbricate.
TimeoutException – Excepția care este aruncată atunci când timpul alocat pentru un proces sau o operațiune a expirat.
UnauthorizedAccessException – Excepția care este aruncată atunci când sistemul de operare refuză accesul din cauza unei erori de intrare/ieșire (I/O) sau a unui anumit tip de eroare de securitate.
KeyNotFoundException – Excepția care este aruncată atunci când cheia specificată pentru accesarea unui element dintr-o colecție nu se potrivește cu nicio cheie din respectiva colecție.
DirectoryNotFoundException – Excepția care este aruncată când o parte a unui fișier sau director nu poate fi găsită.
DriveNotFoundException – Excepția care este aruncată atunci când încercați să accesați o unitate sau o partiție care nu este disponibilă.
EndOfStreamException – Excepția care este aruncată la încercarea de citire după sfârșitul unui flux.
FileNotFoundException – Excepția care este aruncată când nu se reușește o încercare de accesare a unui fișier care nu există pe disc.
IOException – Excepția care este aruncată atunci când apare o eroare I/O.
PathTooLongException – Excepția care este aruncată atunci când un nume de cale sau un nume de fișier este mai lung decât lungimea maximă definită de sistem.
COMException – Excepția care este aruncată atunci când un HRESULT necunoscut este returnat dintr-un apel prin metoda COM.
InvalidComObjectException – Excepția aruncată atunci când se utilizează un obiect COM invalid.
SerializationException – Excepția aruncată atunci când apare o eroare în timpul serializării sau deserializării.
SecurityException – Excepția care este aruncată când se detectează o eroare de securitate.
XmlSyntaxException – Excepția care este aruncată atunci când există o eroare de sintaxă în parsarea XML. Această clasă nu poate fi moștenită.
HttpException – Descrie o excepție care a apărut în timpul procesării cererilor HTTP.
HttpParseException – Excepția care este aruncată atunci când apare o eroare de parsare.
SocketException – Excepția care este aruncată atunci când apare o eroare de socket.

Nu trebuie să memorați această listă, ci să o păstrați ca referință ori de câte ori întâlniți excepții.

În următoarea lecție, vom vorbi despre tratarea excepțiilor, astfel încât să nu ne blocheze execuția programelor atunci când apar, ci să le punem în folosul nostru.

Comments

comments

Tags: , ,

Leave a Reply