Kivétel kezelés
Kivétel kezelés Krizsán Zoltán1 Általános Informatikai Tanszék Miskolci Egyetem
Objektumorientált programozás C# alapokon tananyag
Krizsán Zoltán1
1/29
Kivétel kezelés
Tartalom
1
Kivétel kezelés Általános információk Kivétel (Exception) Kivétel kezelés Saját kivétel osztály készítése
Krizsán Zoltán1
2/29
Kivétel kezelés
A kivételkezelés célja
Kivételes helyzetek (hibák) a jól megírt programokban is el®fordulnak. Például: er®forrás hiány (lemez megtelt), valamilyen funkció hiányos vagy hibás adatok miatt nem hajtható végre
Ezeket a szituációkat kezelni kell. A szükséges teend®k elvégzése után általában a program folytatni tudja a munkát.
Krizsán Zoltán1
3/29
Kivétel kezelés
Hagyományos hibakezelés
Függvény visszatérési értéke (paramétere) hátrányai: azonosítás hibaérték / valódi érték megkülönböztetése nehézkes hívási hierarchia!
Ellen®rzés nehézkes, sok helyre kell beiktatni. Kód áttekinthet®ségét rontja! A funkcionális és a hibakezel® kódrészletek keverednek.
Krizsán Zoltán1
4/29
Kivétel kezelés
Tartalom
1
Kivétel kezelés Általános információk Kivétel (Exception) Kivétel kezelés Saját kivétel osztály készítése
Krizsán Zoltán1
5/29
Kivétel kezelés
Kivétel - exception
Futás idej¶ hiba / nem normális eset. Általában valamilyen hibához köt®dik. Számos beépített kivétel. Saját kivétel deniálható. A C# szemléletében a kivétel egy objektum, ami a kivétel bekövetkezésekor jön létre. Saját (programozói) kivétel kiváltása: throw objektum
Krizsán Zoltán1
6/29
Kivétel kezelés
Kivétel - hiba I
A kivétel keletkezésekor szokásos teend®k: értesíteni a felhasználót, vagy naplózni, majd valamilyen plusz m¶veletek után folytatni az alkalmazást, esetleg kilépni, súlyos hiba esetén.
Ellen®rzött kilépés lehetséges. (Például el®tte minden értékes adat elmenthet®.) A kivétel objektum tartalmazhat információkat a kivétel keletkezésér®l, amelyet felhasználhatunk.
Krizsán Zoltán1
7/29
Kivétel kezelés
Tartalom
1
Kivétel kezelés Általános információk Kivétel (Exception) Kivétel kezelés Saját kivétel osztály készítése
Krizsán Zoltán1
8/29
Kivétel kezelés
Kivételkezelés utasításai I
try védett kód (blokk) kijelölése throw kivétel dobása, generálása catch kivétel elkapása, a blokkban deniált utasítások végrehajtása nally végül, akár volt kivétel, akár nem volt, lefut
Krizsán Zoltán1
9/29
Kivétel kezelés
try blokk I
A védett kódot try blokkban helyezzük el: try { utasítások }
A blokkban keletkezett kivételt mi kezelhetjük le. A blokkok egymásba ágyazhatóak. Érdemes minél kisebb blokkokat deniálni. Kivétel keletkezik, ha a try blokkban egy throw utasításra fut a vezérlés. Formája: throw new kivételTípus(konstruktor paraméterek)
A throw paramétere nem maradhat el!
Krizsán Zoltán1
10/29
Kivétel kezelés
Kivétel keletkezése I Kivétel keletkezhet az alábbi módokon: Implicit módon: a C# rendszerb®l indul ki, azaz valamely utasítás vagy API elem végrehajtása során keletkezik. A programozó kódjában keletkezik, közvetlenül egy throw utasítás végrehajtásával. Aszinkron kivétel, amely a program egy másik szálán lépett fel. A kivétel keletkezése esetén: Az els® kivételt kiváltó utasítással befejez®dik a try blokk végrehajtása. Kilép a blokkból a vezérlés, rendcsinálással verem visszaállítása, lokális objektumok megszüntetése, védett változók lezárásának megszüntetése.
Létrejön a throw utasításban megjelölt objektum egy példánya. Krizsán Zoltán1
11/29
Kivétel kezelés
Kivétel elkapása I A kivétel objektumot minden esetben a rendszer hozza létre. A kivétel lekezelését szolgáló utasítások catch blok(kok)ban helyezkednek el. Formája: catch (típus paraméter) {utasítások}
A catch minden esetben a try blokkot követi, nem lehet köztük más utasítás. Egy try blokkhoz tartozhat több catch is. A rendszer megkeresi a sorrendben els® "illeszked®" blokkot, és annak végrehajtásával folytatódik a program. Az illeszkedés feltétele: a kivétel objektum típusa megegyezik a catch blokk fejében megadott típussal, vagy annak leszármazottja. Krizsán Zoltán1
12/29
Kivétel kezelés
Kivétel elkapása II A kiválasztott blokk végrehajtása során a paramétere úgy használható, mint a függvények esetén a formális paraméter. Így lehet felhasználni a kivétel objektumban tárolt információkat. A futás az utolsó catch utáni sorral folytatódik. Ha ha a catch blokk végrehajtása során újabb kivétel keletkezik, az eredeti kivétel kezelése megszakad, és az új kivétel lekezelése kezd®dik el. Ha egyetlen catch blokk sem illeszkedett a kivételre, a keresés a beágyazó try blokk catch blokkjaival folytatódik, amíg sikeres nem lesz. Ha a keresés belülr®l kifelé minden try blokkot megvizsgált, és nem talált egyezést, a program terminálódik, és kiíródik a kivétel stack. (Lekezeletlen kivétel.) Krizsán Zoltán1
13/29
Kivétel kezelés
Kivétel elkapása III
Megjegyzés: a try blokk kivételt kiváltó utasítása utáni utasítások tehát mindig kimaradnak!
Krizsán Zoltán1
14/29
Kivétel kezelés
nally blokk I
Nem kötelez®. A cacth(ek) után szerepelhet. Az utolsó catch blokk és a nally blokk között nem lehet más utasítás. Nem lehet paramétere. Minden esetben lefut. Ha kivétel keletkezett a try blokkban, egy catch blokk végrehajtása után. Ha nem volt kivétel, a try blokk utolsó utasítása után.
Alkalmas például fájlok, adatbázis kapcsolatok lezárására.
Krizsán Zoltán1
15/29
Kivétel kezelés
Egymásba ágyazott try blokkok I
A try blokkok egymásba ágyazhatók közvetlenül, vagy közvetve, amikor a try blokkban egy olyan metódus hívása szerepel, amely tartalmaz try blokkot. Úgy tekinthetjük, hogy a main metódus egy implicit try blokkban fut, és itt kezel®dik le minden olyan kivétel, amelyet egyetlen catch blokk sem kapott el el®tte.
Krizsán Zoltán1
16/29
Kivétel kezelés
Kivétel kezelés egyszer¶ feladat I
Készítsünk alkalmazást, amelyben bekérünk egy számot majd írjuk ki a kétszeresét! Egyszer¶nek t¶nik, de Nem lehet számot bekérni = szöveget kérünk, konvertálni kell. Mi van, ha a felhasználó nem ad meg számot (üres enter)? Mi van, ha megad szöveget, de az nem szám (pl.: 123fecc)?
Krizsán Zoltán1
17/29
Kivétel kezelés
Kivétel kezelés példa I 1 try { 2 String str ; 3 Int32 szam ; 4 5 str = Console . ReadLine () ; 6 7 if ( str . Length == 0) { 8 throw new ApplicationException ("A szoveg ures ! "); 9 } 10 11 szam = Convert . ToInt16 ( str ); 12 Console . WriteLine (" {0} " , szam * 2) ; 13 } Krizsán Zoltán1
18/29
Kivétel kezelés
Kivétel kezelés példa II 14 catch ( System . ApplicationException ex ){ 15 System . Console . WriteLine (" Ures a szoveg ") ; 16 } 17 catch ( FormatException ex ){ 18 System . Console . WriteLine (" Rossz formatum " ); 19 } 20 catch ( System . Exception ex ) { 21 System . Console . WriteLine ( ex . ToString () ) ; 22 } 23 System . Console . WriteLine (" Done ");
Krizsán Zoltán1
19/29
Kivétel kezelés
Hogyan m¶ködhet? I Ha minden jól m¶ködik: futott sorok: 1-7, 11, 12, 23 Convert.Toint16 : konvertálás szövegr®l számra FormatException : ha a beolvasott szöveg nem alakítható számmá. futott sorok: 1-7, 11, 17, 18, 23
OverowException : ha a szöveg konvertálható lenne ugyan számmá, de az túl nagy, vagy kicsi (pl.: 45000) futott sorok: 1-7, 11, 17, 18, 23
throw : ha str.length() == 0 ApplicationException : ha üres a bekért szöveg futott sorok: 1-7, 8, 14, 15, 23
Krizsán Zoltán1
20/29
Kivétel kezelés
Exception osztály I
Lehet®leg, remélhet®leg minden kivétel közvetett, vagy közvetlen ®se. Fontosabb elemei: StackTrace : a kivételek láncolatát érhetjük el InnerException : a következ® kivétel a láncban (kiváltó) Message : kivétel szövege Data : kivételhez kapcsolt információ
Krizsán Zoltán1
21/29
Kivétel kezelés
Kivétel továbbdobása ROSSZ MEGOLDÁS I
Törli a kivétel stack-et. 1 2 3 4 5 6
try { // code here } catch ( Exception ex ){ // some code here related to the exception throw ex ; // Reset the StackTrace to make finding the real problem harder to find 7 }
Krizsán Zoltán1
22/29
Kivétel kezelés
Kivétel továbbdobása JÓ MEGOLDÁS I
1 try { 2 // code here 3 } 4 catch ( Exception ex ){ 5 // some code here related to the exception 6 throw ; // Notice the absence of the ex expression 7 }
Krizsán Zoltán1
23/29
Kivétel kezelés
Kivétel továbbdobása JÓ MEGOLDÁS II I
jobb, mert + információkat lehet felf¶zni, debug-golható. 1 2 3 4 5 6
try { } catch ( Exception ex ) { throw new Exception ( " Put more context here " , ex ) 7 }
Krizsán Zoltán1
24/29
Kivétel kezelés
Tartalom
1
Kivétel kezelés Általános információk Kivétel (Exception) Kivétel kezelés Saját kivétel osztály készítése
Krizsán Zoltán1
25/29
Kivétel kezelés
Kivételek fajtái I
Program által kiváltott. ApplicationException Keretrendszer (CLI) által kiváltott. SystemException
Krizsán Zoltán1
26/29
Kivétel kezelés
Gyakori kivételek I IndexOutOfRangeException: ha túl indexeltük a tömböt. 1 arr [ arr . Length +1] NullReferenceException: ha valahol null objektumon keresztül probáltak elemekhez hozzáférni. 1 object o = null ; 2 o. ToString () ; ArgumentNullException: ha valamely metódus null paramétert kapott 1 2 Krizsán Zoltán1
String s = null ; " Calculate " . IndexOf (s );
27/29
Kivétel kezelés
Saját kivétel osztály készítése I
Az osztály neve legyen Exception vég¶. Pl.: GepElromlottException. sosztály az Exception vagy ApplicatinoException legyen. Tegyük sorosíthatóvá ([Serializable]) Készítsünk 3 konstruktort: paraméter nélkülit 1 paraméterest, amely a hiba szövegét kapja meg (Message tulajdonság). 2 paraméterest, hiba szövegét és a bels® kivételt kapja meg.
Krizsán Zoltán1
28/29
Kivétel kezelés
Saját kivétel példa I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[ Serializable ] public class GepElromlottException : Exception { public GepElromlottException () { } public GepElromlottException ( string message ) : base ( message ) { } public GepElromlottException ( string message , Exception inner ) : base ( message , inner ) { } }
Krizsán Zoltán1
29/29