A try parancs segítségével a programok egyes részeihez hibakezelő rutinokat rendelhetünk, melyek hiba esetén az általunk megírt hibakezelő eljárásokat hajtják végre, s ami nagyon fontos, megakadályozzák a program leállását.
A catch segítségével azokat a kivételeket kaphatjuk el, melyek a try blokkban keletkeznek. Itt határozhatjuk meg, hogy milyen rutinok fussanak le és hogyan kezeljék a felmerülő hibákat. A catch segítségével különböző hibák egyidejű kezelését is megvalósíthatjuk, de erről majd bővebben szólunk a fejezet későbbi részeiben. Most nézzünk meg egy példát a try használatára!
using System;
namespace ConsoleApplication6
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
string s;
int i;
Console.WriteLine("Kérem gépeljen be egy tetszőleges
mondatot!");
s=Console.ReadLine();
try
{
for (i=0;i<20;i++)
{
Console.WriteLine("Az s string {0}. eleme =
{1}",i,s[i]);
}
}
catch
{
Console.WriteLine("Hiba a program futása során...");
}
Console.ReadLine();
}
}
}
Amennyiben futtatjuk a fenti programot, és a beolvasásnál 20 karakternél rövidebb mondatot adunk meg, a hibakezelő eljárás elindul, mivel a try a catch blokkhoz irányítja a vezérlést. A catch blokkban definiált hibakezelő rész lefut, vagyis a képernyőn megjelenik a hibaüzenet.
Abban az esetben, ha nem használjuk a hibakezelő eljárásokat, a programunk leáll, és a hiba kezelését a .NET vagy az operációs rendszer veszi át. Ebből a példából is jól látható milyen nagy szükség lehet a kivételkezelőre, ha jól működő programokat akarunk írni. Fokozottan érvényes ez azokra a programokra, ahol a felhasználó adatokat visz be.
A következő programban erre láthatunk példát. Amennyiben az inputról nem megfelelő adatok érkeznek, működésbe lép a kivétel-kezelés, a catch blokkban elkapjuk a hibát és kiírjuk az okát a képernyőre.
using System;
namespace ConsoleApplication4
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
int i;
try
{
Console.WriteLine("Az i értéke? : ");
i=Convert.ToInt32(Console.ReadLine());
}
catch(Exception e){Console.WriteLine(e.Message);}
Console.ReadLine();
}
}
}
A programban látható, hogy a try után kapcsos zárójelek közt adjuk meg a hibát okozható program részletet. A catch hibakezelő rutinjait szintén kapcsos zárójelek közé kell írni, ezzel jelezve a fordítónak, hogy hol kezdődik és végződik a hibakezelés.
A fenti példában a túlindexelés és a típus különbségek mellett előfordulhatnak más hibák is, melyek a program írásakor rejtve maradnak. Az ilyen jellegű hibákra az előző kód nincs felkészítve, mivel nem definiáltuk a lehetséges hibákat. Ez azt jelenti, hogy a try blokkban előforduló bármely hiba esetén ugyanaz a hibaüzenet jelenik meg a képernyőn.
A catch blokkban lehetőségünk van a különböző okok miatt keletkezett hibák szétválasztására, a hiba típusának meghatározására.
A catch parancs a kivételt paraméterként is fogadhatja, ahogy a fenti példában láthattuk. A paraméterként megadott változó System.Exception típusú, melyből kiolvashatjuk a hiba okát, amit az e.Message rutinnal kapunk meg, és a megfelelő hibakezelőt indíthatjuk el.
catch ( System.Exception e )
{
Console.WriteLine(e.Message);
//hibák kezelése
}
A képernyőn megjelenő hibaüzenet nem nagyon beszédes, illetve gyakran túlságosan sok, nehezen érthető információt tartalmaz. A célunk sem az, hogy a programunk használóját hosszú, értelmezhetetlen üzenetekkel terheljük, mert így nem teszünk többet, mint az eredeti hiba-ablak. Ráadásul a felhasználó nem is nagyon tudja kezelni a keletkezett hibákat, még annak ellenére sem, hogy kiírjuk a képernyőre a hiba minden paraméterét.
Sokkal jobb megoldás, ha megállapítjuk a hiba okát, majd a megfelelő hibakezelés aktivizálásával meg is szüntetjük azt. (Ekkor még mindig ráérünk kiírni a képernyőre, hogy hiba történt, és a javított hibáért a felhasználó nem is haragszik annyira… Talán még elismerően bólint is…)
Írhatunk olyan catch blokkokat is, melyek egy bizonyos típusú hiba elfogására alkalmasak.
int a=0;
double c;
try
{
c = 10 / a + 30;
}
catch (ArithmeticException ar)
{
Console.WriteLine("Aritmetikai hiba : {0}",ar);
}
A catch blokkok sorrendje sem mindegy. A helyes megközelítés az, ha az általános hibák elé helyezzük azokat a hibákat, melyekre már eleve számítani lehet a programban, mint pl.: a fenti matematikai hiba.
A System névtérben rengeteg kivétel típust definiáltak. A fontosabbakat az alábbi táblázatban foglaltuk össze.
Kivétel neve |
Leírása |
MemberAccesException |
Tagfüggvény hozzáférési hiba |
ArgumentException |
Hibás tagfüggvény-paraméter |
ArgumentNullException |
Null értékű tagfüggvény paraméter |
ArithmeticException |
Matematikai művelet-hiba |
ArrayTypeMismatchException |
Tömbtípus hibája (érték tároláskor) |
DivideByZeroException |
Nullával való osztás |
FormatException |
Hibás paraméter-formátum |
IndexOutOfRangeException |
Tömb túl, vagy alulindexelése |
InvalidCastException |
Érvénytelen típus átalakítás |
NotFiniteNumberException |
A keletkezet érték nem véges (hibás számalak) |
NullReferenceException |
Null értékre való hivatkozás |
NotSupportedException |
Nem támogatott tagfüggvény |
OutOfMemoryException |
Elfogyott a memória |
OverflowException |
Túlcsordulás (checked esetén) |
StackOverflowException |
Verem túlcsordulás |
TypeInitializationException |
Hibás típus beállíás (static kontruktornál) |