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