Saturday, February 16, 2019 15:36

Try Catch Finally

Continuând din ultima lecție, știm acum că de fiecare dată când ne ocupăm de coduri care ar putea genera erori, ar trebui să folosim un construct de tip Try Catch. Ar trebui să știți și că această construcție mai oferă o altă caracteristică extraordinară, un bloc Finally. Acest bloc de cod este executat indiferent de modul în care execuția a părăsit partea Try Catch, deci aceasta înseamnă că se va executa chiar și atunci când ar fi generate erori. Acest lucru este minunat deoarece, la fel ca în exemplul nostru de lecția anterioară, am putea avea coduri care ar trebuie să efectueze anumite acțiuni atunci când am terminat cu ele. Mai exact, să spunem că avem de-a face cu citirea sau scrierea unui fișier. Dacă se declanșează o excepție în timp ce se efectuează astfel de acțiuni, partea în care închidem efectiv fluxul către fișierul respectiv și îl eliberăm nu s-ar mai executa. Cu alte cuvinte, fișierul va rămâne blocat, considerând că este încă procesat de codul nostru. Nu îl vom putea muta, redenumi sau șterge până nu închidem conexiunea către el din codului nostru.

De aceea, folosind un bloc de cod Finally, care se execută de fiecare dată când executăm blocul Try, putem pune codurile pentru eliberarea fișierului în interiorul acestuia, asigurându-ne că, indiferent de ce se întâmplă, nu îl vom bloca.

Forma de bază a unui bloc Finally arată astfel:

Desigur, putem folosi și părțile de manipulare a excepțiilor:

Am spus mai sus că un cod dintr-un bloc Finally va fi executat de fiecare dată, indiferent de ce se întâmplă în blocurile Try sau Catch. Fiți conștienți totuși, am vrut să spună că se va executa de fiecare dată când executăm un bloc Try, nu de sine însuși. Nu putem avea un bloc Finally fără un bloc Try atașat la acesta. De asemenea, observați că blocul Finally nu va fi executat dacă programul este terminat din exterior, cum ar fi închiderea acestuia din Task Manager.

Deși putem avea mai multe blocuri Catch atașate la o construcție Try, putem avea doar un bloc unic Finally atașat la un Try.

Acum, să luăm exemplul citirii unui fișier din lecția anterioară și să îl analizăm puțin:

Putem vedea în mod clar că instrucțiunea cititor.Close();, cea care răspunde de eliberarea fișierului, se află pe ultima linie a blocului nostru Try. Dar, ce se întâmplă dacă am obține o eroare pe a doua linie, în timp ce citim fișierul? În cazul acesta, execuția va fi transferată în blocul Catch, iar linia care eliberează fișierul nu va fi executată niciodată. Doar ce am rămas cu un fișier pe care nu îl putem modifica, muta, șterge, redenumi, etc., până când ne închidem programul și este eliberat. În schimb, să re-gândim codul nostru, folosind constructul Finally:

Puteți vedea câteva diferențe. Prima este evident, faptul că am adăugat un construct Finally la blocul nostru Try. Cel de-al doilea lucru pe care îl observați este faptul că am declarat cititorul înainte de a începe blocul Try, în afara acestuia. Dacă vă amintiți din lecția despre domeniul de definiție, o variabilă declarată în interiorul unui bloc este vizibilă doar în interiorul acelui bloc și toate celelalte blocuri care sunt blocuri copii ale blocului în care este declarată variabila. Deci, tot ce este în interiorul său, nimic în afara sa. În consecință, dacă vom declara variabila în interiorul blocului Try, acesta va fi vizibil doar pentru codurile din interiorul blocului și pentru orice blocuri care trăiesc în interiorul acestuia. Cu toate acestea, blocul Finally este un bloc complet diferit, la același nivel cu cel Try. Aceasta înseamnă că variabila cititor nu ar fi vizibilă și recunoscută în interiorul acestuia. Prin declararea ei în afara blocurilor Try și Finally, este vizibilă în interiorul ambelor părți și putem efectua acțiuni asupra acesteia. Al treilea lucru de observat este faptul că atunci când am declarat variabila noastră cititor, am inițializat-o, și am inițializat-o cu o valoare null. Acest lucru se datorează faptului că, amintiți-vă, modalitatea de a inițializa o variabilă cititor este dându-i calea către un nume de fișier. Dar dacă fișierul nu există, vom obține o excepție de tip System.IO.FileNotFoundException. Nu vrem să facem asta în afara blocului nostru Try, sau ne va bloca programul. Din acest motiv, o declarăm ca fiind nulă și doar o inițializăm în interiorul părții Try. Acest lucru ne duce și la cel de-al patrulea lucru pe care trebuie să-l observați: în blocul Finally, trebuie să verificăm dacă variabila cititor nu este nulă înainte să încercăm să o închidem. Acest lucru se datorează faptului că, dacă fișierul nu există? Am inițializat variabila noastră ca fiind nulă, iar dacă fișierul nu există, vom obține o excepție în interiorul blocului Try, care va transfera execuția în blocurile Catch. Dar aceasta va lăsa totuși variabila noastră tot nulă, așa cum am inițializat prima oară. Și nu putem efectua nicio acțiune asupra unei variabile nule, inclusiv încercarea de a închide un cititor. Dacă am face asta, am avea de asemenea o excepție, și din moment ce excepția ar fi aruncată în afara unui bloc Try, programul nostru tot s-ar bloca.

Comments

comments

Tags: , ,

Leave a Reply