Zpracování chyb a výjimek
3. Neošetřené výjimky
Pokud se stane, že neošetříme možnou chybu v těle po příkazu try uvnitř metody, tzn., že nastane taková výjimka, pro kterou nebude definován příslušný handler s catch, nastane ukončení této metody, v níž nastala chyba.
Pokud by stejný případ nastal u volané metody, která je umístěna v bloku try volající metody a ve volané metodě by došlo k chybě a volaná metoda by neobsahovala příslušný handler, je řízení přepnuto zpět do volající metody. Pokud i volající metoda neobsahuje příslušný handler výjimky, je metoda ukončena a následně je ukončen i celý program v důsledku neošetřené výjimky.
Pokud by tato volající metoda byla volána z jiné metody, je tato jiná metoda prozkoumána, zda neobsahuje odpovídající handler (metody jsou kaskádově prozkoumávány v rámci nalezení příslušného handleru). Pokud je nalezen odpovídající handler s catch, je spuštěn kód v tomto handleru a kód pokračuje prvním příkazem za tělem handleru, který danou výjimku zachytil. [6]
Ilustrativní příklad Vyjimky
Program Vyjimky
- Popis: Princip hledání příslušného handleru při kaskádovém volání metod (absence výjimky ve volané metodě)
- Zadání: Navrhněte program, který v hlavní statické metodě Main v bloku příkazu catch volá metodu s celočíselným návratem s názvem Metoda1. V Main vytvořte handler, který obsluhuje výjimku typu FormatException, která je vyvolána v případě chyby při konverzi. Samotné zadání celého čísla proběhne v jiné statické metodě s návratem nazvané jako Metoda2. V této metodě však chybí příslušný handler pro ošetření chyby na vstupu (při konverzi). V metodě Metoda2 je zadáno celé číslo a toto číslo je zároveň jejím návratem. Aby byl zajištěn princip kaskádování, v těle Metoda1 zavolejte statickou metodu s celočíselným návratem Metoda2 (metoda Main volá metodu Metoda1, která volá metodu Metoda2). Abychom věděli, ve které části programu se nacházíme, do hlavní metody Main do příkazu catch umístěte výpis textu "Handler v metodě Main". V Main za příkaz catch pak umístěte výpis textu "Příkaz za handlerem v metodě Main". Do metody Metoda2 umístěte za načtení čísla výpis "Handler v metodě Metoda2"
- Řešení: Bude postupně probráno v následujícím textu
Následující příklad ilustruje podstatu kaskádového volání jednotlivých metod a absence dané výjimky u poslední
volané metody, kde by potenciálně mohla nastat chyba. Vše začíná voláním statické metody nazvané Metoda1, která vrací obdržený výsledek do
statické hlavní metody Main - viz Kód 1.
Tato metoda Metoda1 ve svém těle volá další statickou
metodu Metoda2 - viz Kód 2.
static void Main(string[] args) { //Deklarace celočíselné proměnné int vysledek; //Hlídaný příkaz try { //Návrat výsledku metody Metoda1 do proměnné vysledek vysledek = Metoda1(); } //Handler - obsluha výjimky vyvolané chybou při konverzi catch (FormatException e) { //Výpis textu Console.WriteLine("Handler v metodě Main"); } //Výpis textu Console.Write("Příkaz za handlerem v metodě Main"); //Čekání na stisk klávesy -> ukončení programu Console.ReadKey(); }
Kód 1: Deklarace hlavní statické metody Main - obsahuje handler pro ošetření vyvolané výjimky v jiné metodě
V těle metody Metoda1 vidíme, že Metoda2 vrací celočíselnou načtenou hodnotu do volající metody Metoda1 - viz Kód 2.
//Deklarace volané metody z metody Main static int Metoda1() { //Návrat výsledku z voláné metody Metoda2 return Metoda2(); }
Kód 1: Deklarace statické metody Metoda1 - volání metody Metoda2
Výsledek obdržený z Metoda2 představuje celé číslo, získané konverzí textového řetězce zadaného uživatelem na klávesnici - viz Kód 3. To vše by bylo v pořádku až do té doby, kdy uživatel namísto textu představujícím číslice zadá text např. „bflm“. V tu dobu nastane chyba při konverzi u příkazu int.Parse, protože text nelze konvertovat na celé číslo. Dalším problém je, že v Metoda2 chybí odpovídající handler pro ošetření chyby na vstupu typu FormatException. Tento handler jsme záměrně umístili do metody Main, která provedla volání metody jako první (metoda Main volá metodu Metoda1, která volá metodu Metoda2). Pokud tedy platí princip uvedený v předchozím textu, mělo by být provedeno ošetření výjimky v metodě, která jako první nejbližší obsahuje daný handler, tedy metoda Main.
//Deklarace volané metody z metody Metoda1 static int Metoda2() { //Deklarace proměnné int x; //Výpis pro zadání Console.Write("Zadejte celé číslo: "); /*Konverze načtené textového řetezce od uživatele a uložení do proměnné x*/ x = int.Parse(Console.ReadLine()); //Výpis textu Console.WriteLine("Handler v metodě Metoda2"); //Návrat výsledku do volající metody return x; }
Kód 1: Deklarace statické metody Metoda2 - absence handleru pro ošetření výjimky
Dokážete si tipnout, jaký bude výpis v konzoli? Záměrně jsme do metod ještě umístili výpis, abychom poznali, jaký kód se bude po ošetření výjimky provádět. Výsledek je zobrazen na následujícím výpisu – viz Výstup programu - Kód 1. Na výpisu v konzoli vidíme, že příkaz výpisu v metodě Metoda2 se vůbec neprovedl, ale provedl se pouze kód za příslušným handlerem nalezeným v metodě Main.
Zadejte celé číslo: bflm Handler v metodě Main Příkaz za handlerem v metodě Main
Výstup
programu - Kód 1: Ukázka výsledku u hledání příslušného handleru