Cvičení – vytvoření a vyvolání výjimky
Vývojáři často potřebují vytvářet a vyvolávat výjimky v rámci metody a pak tyto výjimky zachytávat výše v zásobníku volání, kde je lze zpracovat. Zpracování výjimek vám pomůže zajistit stabilitu aplikací.
V tomto cvičení začnete ukázkovou aplikací, která zahrnuje potenciální chybový stav uvnitř volané metody. Aktualizovaná metoda vyvolá throw výjimku, poté co zjistí problém. Výjimka bude zpracována catch v bloku kódu, který volá metodu. Výsledkem je aplikace, která poskytuje lepší uživatelské prostředí.
Vytvoření nového projektu kódu
Prvním krokem je vytvoření projektu kódu, který můžete použít během tohoto modulu.
Otevřete novou instanci editoru Visual Studio Code.
V nabídce Soubor vyberte Otevřít složku.
V dialogovém okně Otevřít složku přejděte do složky Windows Desktop .
V dialogovém okně Otevřít složku vyberte Nová složka.
Pojmenujte novou složku ThrowExceptions101 a pak vyberte Vybrat složku.
V nabídce Terminál vyberte Nový terminál.
K vytvoření nové konzolové aplikace použijete příkaz .NET CLI.
Na příkazovém řádku panelu TERMINÁL zadejte následující příkaz:
dotnet new consoleZavřete panel TERMINÁL.
Kontrola ukázkové aplikace
Pomocí následujících kroků načtěte a zkontrolujte ukázkovou aplikaci.
Otevřete soubor Program.cs.
V nabídce Zobrazit vyberte paletu příkazů.
Na příkazovém řádku zadejte .net: g a pak vyberte .NET: Generovat prostředky pro sestavení a ladění.
Obsah souboru Program.cs nahraďte následujícím kódem:
// Prompt the user for the lower and upper bounds Console.Write("Enter the lower bound: "); int lowerBound = int.Parse(Console.ReadLine()); Console.Write("Enter the upper bound: "); int upperBound = int.Parse(Console.ReadLine()); decimal averageValue = 0; // Calculate the sum of the even numbers between the bounds averageValue = AverageOfEvenNumbers(lowerBound, upperBound); // Display the value returned by AverageOfEvenNumbers in the console Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}."); // Wait for user input Console.ReadLine(); static decimal AverageOfEvenNumbers(int lowerBound, int upperBound) { int sum = 0; int count = 0; decimal average = 0; for (int i = lowerBound; i <= upperBound; i++) { if (i % 2 == 0) { sum += i; count++; } } average = (decimal)sum / count; return average; }Projděte si kód za minutu.
Všimněte si, že aplikace provádí následující úlohy:
Příkazy nejvyšší úrovně používají
Console.ReadLine()příkazy k získání hodnot prolowerBoundaupperBound.Příkazy nejvyšší úrovně předávají
lowerBoundaupperBoundjako argumenty při voláníAverageOfEvenNumbersmetody.Metoda
AverageOfEvenNumbersprovádí následující úkoly:- Deklaruje místní proměnné používané při výpočtech.
- Pomocí smyčky
forsečte sudá čísla mezilowerBoundaupperBound. Součet je uložen vsum. - Spočítá, kolik čísel je součástí součtu. Počet je uložen v
count. - Uloží průměr sečtených čísel do proměnné s názvem
average. Hodnotaaverageje vrácena.
Příkazy nejvyšší úrovně vytisknou hodnotu vrácenou konzolou
AverageOfEvenNumbersa pak pozastaví provádění.
Nakonfigurujte prostředí ladění
Ukázková aplikace čte uživatelský vstup z konzoly. Panel KONZOLY LADĚNÍ nepodporuje čtení vstupu z konzoly. Než budete moci tuto aplikaci spustit v debuggeru, musíte aktualizovat soubor launch.json.
Pomocí zobrazení PRŮZKUMNÍK otevřete soubor launch.json.
V souboru launch.json aktualizujte
consoleatribut následujícím způsobem:// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console":"integratedTerminal",Výchozí hodnota atributu
consolejeinternalConsole, která odpovídá panelu KONZOLY LADĚNÍ. Panel KONZOLY LADĚNÍ bohužel nepodporuje vstup konzoly. NastaveníintegratedTerminalse zarovná na panel TERMINÁL, který podporuje vstup a výstup konzoly.Uložte změny do souboru launch.json a potom soubor zavřete.
V nabídce Visual Studio Code Spustit, vyberte Spustit ladění.
Přepněte na panel TERMINÁL.
Na příkazovém řádku "dolní mez" zadejte 3.
Do výzvy "horní mez" zadejte 11.
Všimněte si, že aplikace zobrazí následující zprávu a pak se pozastaví:
The average of even numbers between 3 and 11 is 7.Aplikaci ukončíte stisknutím klávesy Enter.
Vyvolání výjimky v metodě AverageOfEvenNumbers
Metoda AverageOfEvenNumbers očekává horní mez, která je větší než dolní mez. K DivideByZero chybě dojde, pokud je dolní mez větší nebo rovna horní hranici.
Je třeba aktualizovat metodu AverageOfEvenNumbers, aby vyvolala výjimku, pokud je dolní mez větší nebo rovna horní mezi.
Chvíli zvažte, jak chcete tento problém vyřešit.
Jednou z možností je zabalit výpočet
averageuvnitřtrybloku kódu acatchDivideByZerovýjimku, když k ní dojde. Výjimku můžete znovu vyvolat a pak ji zpracovat ve volajícím kódu.Další možností je vyhodnotit vstupní parametry před zahájením výpočtů. Pokud
lowerBoundje větší nebo rovnoupperBound, můžete vyvolat výjimku.Lepší volbou je vyhodnocení parametrů a vyvolání výjimky před zahájením výpočtů.
Zvažte, jaký typ výjimky chcete vyvolat.
Existují dva typy výjimek, které odpovídají problému:
-
ArgumentOutOfRangeExceptionArgumentOutOfRangeException- Typ výjimky by měl být vyvolán pouze v případě, že hodnota argumentu je mimo povolený rozsah hodnot definovaný vyvolanou metodou. AčkoliAverageOfEvenNumbersexplicitně nedefinuje povolený rozsah prolowerBoundneboupperBound, hodnotalowerBoundimplikuje povolený rozsah proupperBound. -
InvalidOperationException: TypInvalidOperationExceptionvýjimky by měl být vyvolán pouze v případě, že provozní podmínky metody nepodporují úspěšné dokončení konkrétního volání metody. V tomto případě jsou provozní podmínky vytvořeny vstupními parametry metody.
Pokud máte dva nebo více typů výjimek, ze kterých si můžete vybrat, vyberte typ výjimky, který tomuto problému více vyhovuje. V tomto případě jsou tyto dva typy výjimek stejně sladěné s problémem.
Pokud máte dva nebo více typů výjimek, které odpovídají problému stejně, vyberte typ výjimky s nejmenším rozsahem.
ArgumentOutOfRangeExceptionTyp výjimky je vymezen na argumenty předané metodě. TypInvalidOperationExceptionvýjimky je vymezen na provozní podmínky metody. V tomto případě je typ výjimkyArgumentOutOfRangeExceptionzúženější než typ výjimkyInvalidOperationException.Metoda
AverageOfEvenNumbersby měla vyvolatArgumentOutOfRangeExceptionvýjimku.-
Na začátku metody
AverageOfEvenNumbers, abyste detekovali problém s horní hranicí, aktualizujte kód následujícím způsobem:if (lowerBound >= upperBound) { } int sum = 0;Pokud chcete vytvořit a vyvolat
ArgumentOutOfRangeExceptionvýjimku, aktualizujteifblok kódu následujícím způsobem:if (lowerBound >= upperBound) { throw new ArgumentOutOfRangeException("upperBound", "ArgumentOutOfRangeException: upper bound must be greater than lower bound."); }Tento řádek kódu inicializuje novou instanci
ArgumentOutOfRangeExceptiontřídy s názvem vstupního parametru, který způsobuje výjimku a zadanou chybovou zprávu.
Zachyťte výjimku ve volajícím kódu
Kdykoli je to možné, výjimky by měly být zachyceny na úrovni zásobníku volání, kde je lze zpracovat. V této ukázkové aplikaci je možné parametry AverageOfEvenNumbers metody spravovat ve volající metodě (příkazy nejvyšší úrovně).
Posuňte se nahoru k výrokům nejvyšší úrovně.
Chcete-li uzavřít
AverageOfEvenNumbersvolání metody aConsole.WriteLinepříkaz dotrybloku kódu, aktualizujte kód následujícím způsobem:try { // Calculate the sum of the even numbers between the bounds averageValue = AverageOfEvenNumbers(lowerBound, upperBound); // Display the result to the user Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}."); }Pokud chcete vytvořit přidruženou
catchklauzuli, zadejte následující kód:catch(ArgumentOutOfRangeException ex) { }Zvažte, jak můžete výjimku zpracovat.
Pokud chcete tuto výjimku zpracovat, váš kód musí provést následující:
- Vysvětlete problém uživateli.
- Získání nové hodnoty pro
upperBound. - Zavolejte
AverageOfEvenNumberspomocí novéhoupperBound. - Pokračujte k
catchvýjimce, pokud je nováupperBoundposkytnutá položka stále menší nebo rovnalowerBound.
Pokračovat ve
catchvýjimce vyžaduje cyklus. Vzhledem k tomu, že chcete metoduAverageOfEvenNumbersvolat alespoň jednou, měla by se použít smyčkado.Pro uzavření bloků
tryacatchuvnitř smyčkydoaktualizujte kód následujícím způsobem:do { try { // Calculate the sum of the even numbers between the bounds averageValue = AverageOfEvenNumbers(lowerBound, upperBound); // Display the result to the user Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}."); } catch (ArgumentOutOfRangeException ex) { } }Výraz
whilese vyžaduje k definování výstupní podmínky smyčkydo. Před definováním obsahu bloku kódu je obtížné určit podmínkudo.catchDokončení bloku kódu vám pomůže definovatwhilepožadovaný výraz.Pokud chcete problém uživateli vysvětlit a získat nový
upperBound, aktualizujtecatchblok kódu následujícím způsobem:catch (ArgumentOutOfRangeException ex) { Console.WriteLine("An error has occurred."); Console.WriteLine(ex.Message); Console.WriteLine($"The upper bound must be greater than {lowerBound}"); Console.Write($"Enter a new upper bound: "); upperBound = int.Parse(Console.ReadLine()); }Aktualizovaný
catchblok kódu popisuje problém a vyžaduje, aby uživatel zadal novou horní mez. Co když ale uživatel nemá platnou horní mez, kterou chcete zadat? Co když uživatel potřebuje ukončit smyčku místo zadání hodnoty?Pokud chcete uživateli poskytnout možnost ukončit smyčku místo zadání nové horní hranice, aktualizujte
catchblok kódu následujícím způsobem:catch (ArgumentOutOfRangeException ex) { Console.WriteLine("An error has occurred."); Console.WriteLine(ex.Message); Console.WriteLine($"The upper bound must be greater than {lowerBound}"); Console.Write($"Enter a new upper bound (or enter Exit to quit): "); string? userResponse = Console.ReadLine(); if (userResponse.ToLower().Contains("exit")) { } else { upperBound = int.Parse(userResponse); } }Aktualizovaný
catchblok kódu obsahuje dvě cesty, cestu "exit" a "novou horní mez".Věnujte chvilku úvaze o výrazu
while, který je potřebný pro smyčkudo.Pokud uživatel na příkazovém řádku zadá "Exit", měl by kód ukončit smyčku. Pokud uživatel zadá novou horní mez, měla by smyčka pokračovat. Lze použít
whilevýraz, který vyhodnotí logickou hodnotu. Například:while (exit == false);Navrhovaný
whilevýraz vytvoří následující chování:- smyčka
dobude pokračovat v iteraci, dokud je logická hodnotaexitrovnafalse. - smyčka
dopřestane iterovat, jakmile je logická hodnotaexitrovnatrue.
- smyčka
Pokud chcete vytvořit instanci logické proměnné s názvem
exita použítexitk nastavení ukončovací podmínkydosmyčky, aktualizujte kód následujícím způsobem:bool exit = false; do { try { // Calculate the sum of the even numbers between the bounds averageValue = AverageOfEvenNumbers(lowerBound, upperBound); // Display the result to the user Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}."); exit = true; } catch (ArgumentOutOfRangeException ex) { Console.WriteLine("An error has occurred."); Console.WriteLine(ex.Message); Console.WriteLine($"The upper bound must be greater than {lowerBound}"); Console.Write($"Enter a new upper bound (or enter Exit to quit): "); string? userResponse = Console.ReadLine(); if (userResponse.ToLower().Contains("exit")) { exit = true; } else { exit = false; upperBound = int.Parse(userResponse); } } } while (exit == false);Uložte aktualizovaný kód.
V nabídce Spustit vyberte Spustit ladění.
Přepněte na panel TERMINÁL.
Na příkazovém řádku "dolní mez" zadejte 3.
Do výzvy "horní mez" zadejte 3.
Všimněte si, že na panelu TERMINÁL se zobrazí následující výstup:
Enter the lower bound: 3 Enter the upper bound: 3 An error has occurred. ArgumentOutOfRangeException: upper bound must be greater than lower bound. (Parameter 'upperBound') The upper bound must be greater than 3 Enter a new upper bound (or enter Exit to quit):Na příkazovém řádku pro novou horní mez zadejte 11.
Všimněte si, že na panelu TERMINÁL se zobrazí následující výstup:
Enter the lower bound: 3 Enter the upper bound: 3 An error has occurred. ArgumentOutOfRangeException: upper bound must be greater than lower bound. (Parameter 'upperBound') The upper bound must be greater than 3 Enter a new upper bound (or enter Exit to quit): 11 The average of even numbers between 3 and 11 is 7.Aplikaci ukončíte stisknutím klávesy Enter.
Gratulujeme! Úspěšně jste vyvolali, zachytili a zpracovali výjimku.
Rekapitulace
Tady je několik důležitých věcí, které je potřeba si z této lekce zapamatovat:
- Ujistěte se, že je vaše ladicí prostředí nakonfigurované tak, aby podporovalo požadavky vaší aplikace.
- Kód metody by měl vyvolat výjimku při zjištění problému nebo podmínky.
- Výjimky by měly být zachyceny na úrovni zásobníku volání, kde je možné je vyřešit.