Cvičení – vytvoření a vyvolání výjimky

Dokončeno

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.

  1. Otevřete novou instanci editoru Visual Studio Code.

  2. V nabídce Soubor vyberte Otevřít složku.

  3. V dialogovém okně Otevřít složku přejděte do složky Windows Desktop .

  4. V dialogovém okně Otevřít složku vyberte Nová složka.

  5. Pojmenujte novou složku ThrowExceptions101 a pak vyberte Vybrat složku.

  6. V nabídce Terminál vyberte Nový terminál.

    K vytvoření nové konzolové aplikace použijete příkaz .NET CLI.

  7. Na příkazovém řádku panelu TERMINÁL zadejte následující příkaz:

    dotnet new console
    
  8. Zavřete panel TERMINÁL.

Kontrola ukázkové aplikace

Pomocí následujících kroků načtěte a zkontrolujte ukázkovou aplikaci.

  1. Otevřete soubor Program.cs.

  2. V nabídce Zobrazit vyberte paletu příkazů.

  3. Na příkazovém řádku zadejte .net: g a pak vyberte .NET: Generovat prostředky pro sestavení a ladění.

  4. 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;
    }
    
  5. Projděte si kód za minutu.

    Všimněte si, že aplikace provádí následující úlohy:

    1. Příkazy nejvyšší úrovně používají Console.ReadLine() příkazy k získání hodnot pro lowerBound a upperBound.

    2. Příkazy nejvyšší úrovně předávají lowerBound a upperBound jako argumenty při volání AverageOfEvenNumbers metody.

    3. Metoda AverageOfEvenNumbers provádí následující úkoly:

      1. Deklaruje místní proměnné používané při výpočtech.
      2. Pomocí smyčky for sečte sudá čísla mezi lowerBound a upperBound. Součet je uložen v sum.
      3. Spočítá, kolik čísel je součástí součtu. Počet je uložen v count.
      4. Uloží průměr sečtených čísel do proměnné s názvem average. Hodnota average je vrácena.
    4. Příkazy nejvyšší úrovně vytisknou hodnotu vrácenou konzolou AverageOfEvenNumbers a 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.

  1. Pomocí zobrazení PRŮZKUMNÍK otevřete soubor launch.json.

  2. V souboru launch.json aktualizujte console atribut 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 console je internalConsole, která odpovídá panelu KONZOLY LADĚNÍ. Panel KONZOLY LADĚNÍ bohužel nepodporuje vstup konzoly. Nastavení integratedTerminal se zarovná na panel TERMINÁL, který podporuje vstup a výstup konzoly.

  3. Uložte změny do souboru launch.json a potom soubor zavřete.

  4. V nabídce Visual Studio Code Spustit, vyberte Spustit ladění.

  5. Přepněte na panel TERMINÁL.

  6. Na příkazovém řádku "dolní mez" zadejte 3.

  7. Do výzvy "horní mez" zadejte 11.

  8. 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.
    
  9. 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.

  1. Chvíli zvažte, jak chcete tento problém vyřešit.

    Jednou z možností je zabalit výpočet average uvnitř try bloku kódu a catchDivideByZero vý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 lowerBound je větší nebo rovno upperBound, můžete vyvolat výjimku.

    Lepší volbou je vyhodnocení parametrů a vyvolání výjimky před zahájením výpočtů.

  2. Zvažte, jaký typ výjimky chcete vyvolat.

    Existují dva typy výjimek, které odpovídají problému:

    • ArgumentOutOfRangeException ArgumentOutOfRangeException- 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čkoli AverageOfEvenNumbers explicitně nedefinuje povolený rozsah pro lowerBound nebo upperBound, hodnota lowerBound implikuje povolený rozsah pro upperBound.
    • InvalidOperationException: Typ InvalidOperationException vý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. ArgumentOutOfRangeException Typ výjimky je vymezen na argumenty předané metodě. Typ InvalidOperationException výjimky je vymezen na provozní podmínky metody. V tomto případě je typ výjimky ArgumentOutOfRangeException zúženější než typ výjimky InvalidOperationException.

    Metoda AverageOfEvenNumbers by měla vyvolat ArgumentOutOfRangeException výjimku.

  3. 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;    
    
  4. Pokud chcete vytvořit a vyvolat ArgumentOutOfRangeException výjimku, aktualizujte if blok 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 ArgumentOutOfRangeException tří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ě).

  1. Posuňte se nahoru k výrokům nejvyšší úrovně.

  2. Chcete-li uzavřít AverageOfEvenNumbers volání metody a Console.WriteLine příkaz do try bloku 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}.");
    }
    
  3. Pokud chcete vytvořit přidruženou catch klauzuli, zadejte následující kód:

    catch(ArgumentOutOfRangeException ex)
    {
    
    }
    
  4. 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 AverageOfEvenNumbers pomocí nového upperBound.
    • Pokračujte k catch výjimce, pokud je nová upperBound poskytnutá položka stále menší nebo rovna lowerBound.

    Pokračovat ve catch výjimce vyžaduje cyklus. Vzhledem k tomu, že chcete metodu AverageOfEvenNumbers volat alespoň jednou, měla by se použít smyčka do .

  5. Pro uzavření bloků try a catch uvnitř smyčky do aktualizujte 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 while se vyžaduje k definování výstupní podmínky smyčky do . Před definováním obsahu bloku kódu je obtížné určit podmínku do . catch Dokončení bloku kódu vám pomůže definovat while požadovaný výraz.

  6. Pokud chcete problém uživateli vysvětlit a získat nový upperBound, aktualizujte catch blok 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ý catch blok 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?

  7. Pokud chcete uživateli poskytnout možnost ukončit smyčku místo zadání nové horní hranice, aktualizujte catch blok 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ý catch blok kódu obsahuje dvě cesty, cestu "exit" a "novou horní mez".

  8. Věnujte chvilku úvaze o výrazu while, který je potřebný pro smyčku do.

    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 while výraz, který vyhodnotí logickou hodnotu. Například:

    while (exit == false);
    

    Navrhovaný while výraz vytvoří následující chování:

    • smyčka do bude pokračovat v iteraci, dokud je logická hodnota exit rovna false.
    • smyčka do přestane iterovat, jakmile je logická hodnota exit rovna true.
  9. Pokud chcete vytvořit instanci logické proměnné s názvem exita použít exit k nastavení ukončovací podmínky do smyč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);
    
  10. Uložte aktualizovaný kód.

  11. V nabídce Spustit vyberte Spustit ladění.

  12. Přepněte na panel TERMINÁL.

  13. Na příkazovém řádku "dolní mez" zadejte 3.

  14. Do výzvy "horní mez" zadejte 3.

  15. 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):
    
  16. Na příkazovém řádku pro novou horní mez zadejte 11.

  17. 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.
    
  18. 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.