Prozkoumání výjimek a procesu zpracování výjimek
- 11 min
Chyby za běhu v aplikaci v jazyce C# se spravují pomocí mechanismu označovaného jako výjimky. Výjimky poskytují strukturovaný, jednotný a typově bezpečný způsob zpracování chyb na úrovni systému i chybových podmínek na úrovni aplikace. Výjimky jsou generovány modulem runtime .NET nebo kódem v aplikaci.
Běžné scénáře, které vyžadují zpracování výjimek
Existuje několik programovacích scénářů, které vyžadují zpracování výjimek. Mnoho z těchto scénářů zahrnuje určitou formu získávání dat. I když některé scénáře zahrnují techniky kódování, které jsou mimo rozsah tohoto trénování, stojí za zmínku.
Mezi běžné scénáře, které vyžadují zpracování výjimek, patří:
Uživatelský vstup: Výjimky můžou nastat, když kód zpracovává uživatelský vstup. K výjimkám dochází například v případě, že je vstupní hodnota v nesprávném formátu nebo mimo rozsah.
Zpracování a výpočty dat: Výjimky mohou nastat, když kód provádí výpočty nebo převody dat. K výjimkám dochází například v případě, že se kód pokusí vydělit nulou, přetypovat na nepodporovaný typ nebo přiřadit hodnotu, která je mimo rozsah.
Operace vstupu a výstupu souboru: Výjimky můžou nastat, když kód načítá nebo zapisuje do souboru. K výjimkám dochází například v případě, že soubor neexistuje, program nemá oprávnění k přístupu k souboru nebo ho používá jiný proces.
Databázové operace: Výjimky můžou nastat, když kód komunikuje s databází. Například výjimky nastanou, když dojde ke ztrátě připojení k databázi, dojde k chybě syntaxe v příkazu SQL nebo dojde k narušení omezení.
Síťová komunikace: K výjimkám může dojít, když kód komunikuje přes síť. Například při ztrátě síťového připojení dojde k výjimkám, dojde k vypršení časového limitu nebo vzdálený server vrátí chybu.
Jiné externí prostředky: Výjimky můžou nastat, když kód komunikuje s jinými externími prostředky. Webové služby, rozhraní REST API nebo knihovny třetích stran můžou vyvolat výjimky z různých důvodů. K výjimkám dochází například kvůli problémům se síťovými připojeními, poškozeným datům atd.
Zpracování výjimek – klíčová slova, bloky kódu a vzory
Zpracování výjimek v jazyce C# je implementováno pomocí trycatch, a finally klíčových slov. Každé z těchto klíčových slov má přidružený blok kódu a lze ho použít k splnění konkrétního cíle v přístupu ke zpracování výjimek. Například:
try
{
// try code block - code that may generate an exception
}
catch
{
// catch code block - code to handle an exception
}
finally
{
// finally code block - code to clean up resources
}
Poznámka:
Jazyk C# také umožňuje kódu vygenerovat objekt výjimky pomocí klíčového throw slova. Scénáře zpracování výjimek, které zahrnují použití klíčového throw slova k vygenerování výjimek, jsou popsány v samostatném modulu Microsoft Learn.
Blok try kódu obsahuje strážený kód, který může způsobit výjimku. Pokud kód v bloku try způsobí výjimku, zpracuje se výjimka odpovídajícím catch blokem.
Blok catch kódu obsahuje kód, který se spustí při zachycení výjimky. Blok catch může zpracovat výjimku, protokolovat ji nebo ji ignorovat.
catch Blok lze nakonfigurovat tak, aby se spustil, když dojde k jakémukoli typu výjimky nebo pouze v případě, že dojde k určitému typu výjimky.
Blok finally kódu obsahuje kód, který se spouští bez ohledu na to, jestli dojde k výjimce nebo ne. Blok finally se často používá k vyčištění všech prostředků přidělených v try bloku. Například zajistěte, aby proměnná byla přiřazena správná nebo požadovaná hodnota.
Zpracování výjimek v aplikaci jazyka C# se obecně implementuje pomocí jednoho nebo několika následujících vzorů:
- Vzor
try-catchse skládá ztrybloku následovaného jednou nebo vícecatchklauzulí. Každýcatchblok se používá k určení obslužných rutin pro různé výjimky. - Vzor
try-finallyse skládá ztrybloku následovaného blokemfinally. Příkazy v blokufinallyse obvykle spouštějí, když program dokončí vykonánítrypříkazu. - Vzor
try-catch-finallyimplementuje všechny tři typy bloků zpracování výjimek. Běžným scénářemtry-catch-finallymodelu je získání a použití prostředků vtrybloku, výjimečné okolnosti se spravují vcatchbloku a prostředky se uvolní nebo jinak spravují vfinallybloku.
Jak jsou výjimky reprezentované v kódu?
Výjimky jsou reprezentovány v kódu jako objekty, což znamená, že jsou instancí třídy. Knihovna tříd .NET poskytuje třídy výjimek, ke kterým se přistupuje v kódu stejně jako jiné třídy .NET. Dalším příkladem třídy .NET, která se používá jako objekt v kódu, je Random třída (slouží k vytvoření náhodných čísel).
Přesněji řečeno, výjimky jsou typy reprezentované třídami, které jsou nakonec odvozeny z System.Exception. Třída výjimky odvozená z Exception obsahuje informace, které identifikují typ výjimky a obsahují vlastnosti, které poskytují podrobnosti o výjimce. Podrobnější zkoumání třídy Exception je zahrnuto v pozdější části tohoto modulu.
Instanci třídy za běhu se obecně označuje jako objekt, takže výjimky se často označují jako objekt výjimky.
Poznámka:
I když se někdy používají zaměnitelně, třída a objekt jsou různé věci. Třída definuje typ objektu, ale není to samotný objekt. Objekt je konkrétní entita založená na třídě.
Proces zpracování výjimek
Pokud dojde k výjimce, modul runtime .NET vyhledá nejbližší catch klauzuli, která dokáže výjimku zpracovat. Proces začíná metodou, která způsobila vyvolání výjimky. Nejprve se zkoumá metoda, abyste zjistili, jestli kód, který způsobil výjimku, je uvnitř try bloku kódu. Pokud je kód uvnitř try bloku kódu, catch klauzule přidružené k příkazu try jsou považovány za v pořadí.
catch Pokud klauzule nemohou zpracovat výjimku, metoda, která volala aktuální metodu, je prohledána. Zkoumá se, zda volání metody (do první metody) je uvnitř bloku kódu try. Pokud je volání uvnitř try bloku kódu, jsou přidružené catch klauzule považovány za. Tento proces vyhledávání pokračuje, dokud catch nenajde klauzuli, která dokáže zpracovat aktuální výjimku.
catch Jakmile se zjistí klauzule, která dokáže výjimku zpracovat, modul runtime se připraví k přenosu řízení na první příkaz catch bloku. Před zahájením spuštění catch bloku však modul runtime spustí všechny finally bloky přidružené k příkazům try nalezeným během hledání. Pokud se najde více než jeden finally blok, spustí se v daném pořadí, počínaje tím, který je nejblíže kódu, který způsobil vyvolání výjimky.
Pokud nebyla nalezena žádná catch klauzule pro zpracování výjimky, modul runtime ukončí aplikaci a zobrazí uživateli chybovou zprávu.
Podívejte se na následující ukázku try-finally kódu, která obsahuje vnořený vzor uvnitř try-catch vzoru:
try
{
// Step 1: code execution begins
try
{
// Step 2: an exception occurs here
}
finally
{
// Step 4: the system executes the finally code block associated with the try statement where the exception occurred
}
}
catch // Step 3: the system finds a catch clause that can handle the exception
{
// Step 5: the system transfers control to the first line of the catch code block
}
V tomto příkladu dojde k následujícímu procesu:
- Provádění začíná v bloku kódu vnějšího
trypříkazu. - V bloku kódu vnitřního
trypříkazu se vyvolá výjimka. - Modul runtime najde klauzuli
catchpřidruženou k vnějšímutrypříkazu. - Než modul runtime přenese řízení na první řádek
catchbloku kódu, spustífinallyklauzuli přidruženou k vnitřnímutrypříkazu. - Modul runtime pak přenese řízení na první řádek
catchbloku kódu a spustí kód, který zpracovává výjimku.
V tomto jednoduchém příkladu se vnořené vzory try-catch a try-finally nacházejí v rámci jedné metody, ale více vzorů try-catch a try-finally může být rozmístěno mezi metodami, které volají jiné metody.
Zpracování výjimek a zásobník volání
Při čtení o zpracování výjimek a procesu zpracování výjimek se často zobrazí termín "odvíjení zásobníku volání". Abyste pochopili tento termín, musíte porozumět zásobníku volání a tomu, jak se používá ke sledování "zásobníku" volání metod během provádění kódu.
Zásobník volání si můžete představit jako věž z bloků. Když postavíte věž, začnete jen jedním blokem. Pokaždé, když do věže přidáte blok, umístíte ho nad existující bloky. Když se aplikace spustí v ladicím programu, vstupním bodem aplikace je první vrstva přidaná do zásobníku volání (první blok věže). Pokaždé, když metoda volá jinou metodu, přidá se nová metoda do horní části zásobníku. Když váš kód vystoupí z metody, metoda se odebere ze zásobníku volání.
Poznámka:
V případě konzolové aplikace je vstupním bodem vaší aplikace příkazy nejvyšší úrovně. V zásobníku volání ve Visual Studio Code se tento vstupní bod označuje jako metoda Main.
Uvolnění zásobníku volání je proces, který modul runtime .NET používá, když program C# narazí na chybu. Jedná se o stejný proces, který jste právě zkontrolovali.
Když se vrátíte na analogii blokové věže, když potřebujete odebrat blok z věže, začnete od horní části a odeberete každý blok, dokud nedosáhnete toho, co potřebujete. Tento proces je podobný tomu, jak funguje rozbalování zásobníku volání, kde každá vrstva volání v zásobníku je jako blok ve věži. Když běhové prostředí potřebuje rozbalit zásobník volání, začne od vrchní vrstvy a odebere každou vrstvu volání, dokud nedosáhne té, kterou potřebuje. V tomto případě je vrstva volání, kterou potřebuje, metodou catch , která má klauzuli, která dokáže zpracovat výjimku, ke které došlo.
Rekapitulace
Tady je několik důležitých věcí, které je potřeba si z této lekce zapamatovat:
- Mezi běžné scénáře, které mohou vyžadovat zpracování výjimek, patří vstup uživatele, zpracování dat, vstupně-výstupní operace souborů, databázové operace a síťová komunikace.
- Zpracování výjimek v jazyce C# se implementuje pomocí
trycatch, afinallyklíčových slov. Každé klíčové slovo má přidružený blok kódu, který slouží konkrétnímu účelu. - Výjimky jsou reprezentovány jako typy a odvozeny z
System.Exceptiontřídy v .NET. Výjimky obsahují informace, které identifikují typ výjimky, a vlastnosti, které poskytují další podrobnosti. - Pokud dojde k výjimce, modul runtime .NET vyhledá nejbližší
catchklauzuli, která ji dokáže zpracovat. Hledání začíná metodou, kde byla vyvolána výjimka, a v případě potřeby se přesune dolů ve volacím zásobníku.