A Visual Basic programozási nyelv

Kivételkezelés

Hibakeresés

A Visual Basicnek háromféle működési módja van: tervezési, futási és figyelési mód. A hibafigyelő eszközöket figyelési módban használhatjuk.

A Visual Basic különböző eszközöket kínál futáskövetésre, melyeket érdemes a programunk megírása után felhasználni, azaz a programot ezek igénybevételével lefuttatni. Ezek az eszközök a következők:

Töréspont: a kódban töréspontokat helyezhetünk el, és ha a feldolgozás során a kód ezekhez ér, akkor a program futása felfüggesztődik, és megvizsgálható a program pillanatnyi állapota (változók, jellemzők aktuális értékei, aktív eljárás ...).

Figyelés: ekkor egy megszakítási kifejezés megváltozása vagy igazzá válása esetén belépünk a program-megszakítási módba, ahol ellenőrizhetjük a változók értékeit, illetve meg is változtathatjuk azokat.

Belelépés: lépésenként haladhatunk végig a programon, minden léptetés egy soron következő utasítást hajt végre, majd visszatér megszakítási üzemmódba. Ha egy másik nem védett modulban levő eljárás hívása szerepel az adott sorban, akkor ennek minden utasításán is ugyanígy végiglépkedhetünk. Ha a modul védett, akkor átlépésnek felel meg, azaz az eljárás minden utasítását egy lépésben hajtja végre.

Átlépés: mint a belelépés, de egy eljárás hívásakor a teljes eljárás egyetlen lépésben hajtódik végre.

A Visual Basic akkor lép be megszakítási módba, ha egy utasítás hibát generál, törésponthoz vagy Stop utasításhoz érkezik a végrehajtás, vagy figyelési módban a figyelendő kifejezés értéke igaz lesz vagy megváltozik. A Stop és a töréspont között annyi a különbség, hogy a Stop csak a programsor szerkesztésével távolítható el, míg a töréspont ki/bekapcsolását egy gomb segítségével elvégezhetjük, és a töréspont a project újbóli betöltésekor eltűnik, a Stop viszont megmarad. A Debug rendszerobjektum használatával üzeneteket írathatunk ki a Debug ablakba. (pl. Debug.print "vezeteknev: ";text1.text). Ezeknek a soroknak nincsen semmilyen hatása az .exe fájlban, de azért érdemes őket kitörölni.

Hibakezelés

A Visual Basic felismeri a legáltalánosabb hibákat, és az Err objektumban eltárolja a hibakódot. Ennek alapértelmezett jellemzője a Number tag, ezért erre egyszerűen az Err névvel is hivatkozhatunk (nem kell kiírni, hogy Err.Number ). A program kódjában mi is kiválthatunk hibát az Error hibakód paranccsal, ami beállítja az Err objektumot és meghívja a hibakezelőt. Ha nincsen ilyen, akkor hibaüzenetet kapunk a hibáról.

Az előre látható hibákat lekezelhetjük az On Error GoTo szerkezettel (a hibakezelés egy címke). Pl.:

Function Valami On Error Goto hibakez utasítások Exit Function Hibakez: Hibakezelő rész End Function

Ezt a szerkezetet hívják Error trap-nek, és egyszerre csak egy ilyen lehet aktív. Definiálhatunk több alternatív hibakezelőt is, úgy hogy mindig az éppen megfelelőt használjuk.

A Variant típusnak van egy speciális értéke, az Error, amivel azt jelzi, hogy valamilyen hiba történt az eljárásunkban. Ez lehetővé teszi, hogy az alkalmazás alternatívákat hajtson végre a hiba típusától függően. Ha ismerjük a hibakódokat, akkor az Err függvény segítségével könnyen lekezelhetjük a hibákat egy Select Case utasítással. Saját hibakódokat is készíthetünk, ezek Variant típusban lesznek eltárolva Error kódként (pl. rosszérték=CVError(2020)).

A hibakezelő részből többféleképpen léphetünk ki:

Resume: visszatér a hibát okozó utasításra

Resume Next: a hibát okozó utasítás utáni utasításra tér vissza

Resume sorszam: az ugyanazon eljárásban található sorszam címkére ugrik

Error Err: az utolsó hibát újra kiváltja, és a hívási listán másik hibakezelő rutint keres.

Az eljárásból történő kilépés előtt az On Error Goto 0 utasítással minden, az adott eljárásban levő hibakezelő rutin deaktiválható.

Előfordulhat az az eset, hogy hiba lép fel egy eljárásban, és a Visual Basic egy másik eljárásban talál hibakezelő rutint, majd annak végrehajtása után nem tér vissza abba az eljárásba, ahol a hiba bekövetkezett. Ennek elkerülésére a más eljárások által is használt hibakezelő rutinokat úgy kell megírni, hogy eltárolják a hívás helyét.

Lehetőség van a CTRL+BREAK vagy ESC billentyűk letiltására (ezek megszakítják az alkalmazás futását), illetve hatásuk előtt végrehajthatunk bizonyos utasításokat (pl. fájlok lezárása). A letiltás azért nem túl jó ötlet, mert így a felhasználó nem tud kilépni a programból (ezért csak a program bizonyos részein, ideiglenesen tiltsuk le).

Kivételkezelés VB.NET-ben

A kivételkezelés a.NET keretrendszer egy olyan beépített mechanizmusa, melynek segítségével megtalálhatjuk és kezelhetjük a futásidejű hibákat. A .NET keretrendszer többféle beépített kivétellel rendelkezik. A kivételek olyan anomáliák, melyek a program futás során váltódnak ki. A kiváltódásnak több oka is lehet, például felhasználói hiba, logikai hiba vagy éppen rendszerhiba. Ha a programozó nem biztosít megoldást ezeknek az anomáliáknak a kezelésére, akkor a .NET keretrendszer futtató környezete nyújt általános megoldást: a program terminálni fog.

A VB.NET három kulcsszó használatával biztosítja a kivételkezelés használatát. Ezek a try, catch és a finally. A try-catch-finally blokk általában a következő képen néz ki:

Try ' Utasitasok, melyek kiveteleket valthatnak ki. Catch x As Type ' Utasitasok, melyekkel kezlni lehet a kivaltodott kiveteleket Finally End Try 'Rakjunk rendet

Ha a try blokkban bármilyen kivétel történik, a vezérlés rögtön a megfelelő catch blokkra ugrik, majd utána a finally blokkra. De VB.NET-ben mind a catch mind a finally blokk opcionális. Egy try blokk állhat:

Ha a try blokkban nem történt kivétel, a vezérlés rögtön a finally blokkra ugrik (ha van). Tehát nyugodtan mondhatjuk, hogy a finally blokk mindig lefut. Érdemes megjegyezni, hogy lehetőségünk van kiugrani a finally blokkból a break és a goto utasítások segítségével. VB.NET-ben a kivételek mind Exception típusúak. Az Exception osztály az összes VB.NET-beli kivétel ősosztálya. Mint azt említettem, a .NET keretrendszer biztosít a programozónak jónéhány előre definiált kivételt, de természetesen lehetőség van saját kivételek definiálására is. Ezt az Exception osztályból vagy annak valamely leszármazottjából történő származtatással tehetjük meg.

El nem kapott kivételek

A következő program ugyan le fog fordulni, de a futása során hiba fog történni. A nullával való osztás ugyanis futási idejű hiba, ezért a program hibaüzenettel fog terminálni. Ha egy kivételt nem kapunk el a kiváltódás hatókörében, akkor továbbterjed és a külsőbb környezetben fog keresni megfelelő catch blokkot. Amennyiben sehol sincs ilyen catch blokk, a futtató környezet fogja kezelni a kivételt a program futásának leállításával.

//VB.NET: Kivételkezelés Imports System Class MyClient Public Shared Sub Main() Dim x As Integer = 0 Dim div As Integer = 100 / x Console.WriteLine(div) End Sub 'Main End Class 'MyClient

A fenti kód kivételkezeléssel való bővítése a következőképpen néz ki. Itt a beépített DividedByZeroException osztály egy objektumát kezeljük, ami a nullával való osztás miatt dobódott.

//VB.NET: Kivételkezelés Imports System Class MyClient Public Shared Sub Main() Dim x As Integer = 0 Dim div As Integer = 0 Try div = 100 / x Console.WriteLine("Nem fut le ez a sor") Catch de As DivideByZeroException Console.WriteLine("Kivetel tortent") End Try Console.WriteLine("Az eredmeny {0}", div) End Sub 'Main End Class 'MyClient

Az előbbi esetben a program nem fog váratlanul terminálni. Helyette a vezérlés a kivétel kiváltódásának helyéről (a try blokkból) a catch blokkba ugrik. Ha talál megfelelő catch blokkot, akkor az ott található utasítások végrehajtódnak, majd a program futása "normálisan" folytatódik.

Amennyiben finally blokk is található a kódban, úgy a finally blokkban lévű utasítások is lefutnak.

Imports System Class MyClient Public Shared Sub Main() Dim x As Integer = 0 Dim div As Integer = 0 Try div = 100 / x Console.WriteLine("Nem fut le ez a sor") Catch de As DivideByZeroException Console.WriteLine("Kivetel tortent") Finally Console.WriteLine("Finally Blokk") End Try Console.WriteLine("Az eredmeny {0}", div) End Sub 'Main End Class 'MyClient

Ne felejtsük el, hogy VB.NET-ben a catch blokk opcionális, így a következő kódrész is helyes:

Imports System Class MyClient Public Shared Sub Main() Dim x As Integer = 0 Dim div As Integer = 0 Try div = 100 / x Console.WriteLine("Nem fut le ez a sor") Finally Console.WriteLine("Finally Blokk") End Try Console.WriteLine("Az eredmeny {0}", div) End Sub 'Main End Class 'MyClient

Ebben az esetben, mivel nincs a kivételt lekezelő catch blokk, a program terminálni fog. A finally blokkban szereplő utasítások viszont mindenképpen le fognak futni. VB.NET-ben a try blokkot mindenképpen követnie kell egy catch blokknak vagy egy finally blokknak.

Töbszörös catch blokkok

Egy try blokkban többféle kivétel is kiváltódhat, és ezeket csak több catch blokkal tudunk lekezelni. Ne felejtsük el, hogy a catch blokkok felsorolásánál mindig a speciálisabb típusokkal kezdjük, és így haladunk az általánosabb felé. Más esetben fordítási hibát kapunk.

//VB.NET: Több catch blokk Imports System Class MyClient Public Shared Sub Main() Dim x As Integer = 0 Dim div As Integer = 0 Try div = 100 / x Console.WriteLine("Nem fut le ez a sor") Catch de As DivideByZeroException Console.WriteLine("DivideByZeroException") Catch ee As Exception Console.WriteLine("Exception") Finally Console.WriteLine("Finally Blokk") End Try Console.WriteLine("Az eredmeny {0}", div) End Sub 'Main End Class 'MyClient

Az összes kivétel kezelése

Paraméterek nélküli cacth blokk segítségével olyan kódot készíthetünk, mely a try blokkban kiváltódott össze kivételt kezelni tudja. Természetesen akkor is elkapunk minden kivételt, ha a catch blokkban Exception típusú kivételt várunk. Ez azért van így, mert VB.NET-ben minden kivétel -közvetlenül vagy közvetetten - az Exception ősosztályból származik.

Imports System Class MyClient Public Shared Sub Main() Dim x As Integer = 0 Dim div As Integer = 0 Try div = 100 / x Console.WriteLine("Nem fut le ez a sor) Catch End Try Console.WriteLine("Az eredmeny {0}", div) End Sub 'Main End Class 'MyClient
Imports System Class MyClient2 Public Shared Sub Main() Dim x As Integer = 0 Dim div As Integer = 0 Try div = 100 / x Console.WriteLine("Nem fut le ez a sor") Catch e As Exception Console.WriteLine("oException") End Try Console.WriteLine("Az eredmeny {0}", div) End Sub 'Main End Class 'MyClient2

Kivétel dobás

Az automatikusan kiváltódó kivételek mellett lehetőség van arra is, hogy manuálisan a programozó dobjon tetszőleges kivételt a program bizonyos részeiben. Erre a throw utasítást használjuk. A következő példában bemutatom, hogyan lehet egy ArgumentException típusú kivételt dobni:

Throw New ArgumentException("Exception")

Szokásos kivételek

A kivételeknek két nagy típusa van: A program által generált kivételek és a futtatókörnyezet által generált kivételek. Mint azt már korábban említettük, VB.NET-ben az összes kivétel ősosztálya a System.Exception. Számos osztály őse ez, köztük az ApplicationException és a SystemException osztályoké is. Ebből a két osztályból származik a legtöbb futási idejű kivétel.
A futtatókörnyezet SystemException-öket dob, míg a felhasználói programok ApplicationException-t. A SystemException-ök közé sorolható például az ExecutionEngineException és a StackOverflowException is. Nem ajánlott ezeket a kivételeket elkapni, illetve az sem jó programozói gyakorlat, ha programunkban SystemException típusú kivételeket dobunk.

Néhány példa a SystemException osztály leszármazottjaira:

Saját kivételek
VB.NET-ben lehetőségünk van saját, új kivételek definiálására is. Fontos viszont, hogy mivel ebben a nyelvben az összes kivétel ősosztálya az Exception osztály, ezért új kivételünket kötelező az Exception osztályból vagy annak egy leszármazottjából származtatni.

//Saját kivétel definiálása Imports System Class MyException Inherits Exception Public Sub New(ByVal str As String) Console.WriteLine("Sajat kivetel definialasa") End Sub 'New End Class 'MyException Class MyClient Public Shared Sub Main() Try Throw New MyException("SAJAT KIVETEL") Catch e As Exception Console.WriteLine(("Exception caught here" + e.ToString())) End Try Console.WriteLine("Utolso utasitas") End Sub 'Main End Class 'MyClient