Esercizio - Creare e generare un'eccezione
Gli sviluppatori spesso devono creare e generare eccezioni dall'interno di un metodo e quindi intercettare ulteriormente tali eccezioni nello stack di chiamate in cui possono essere gestite. La gestione delle eccezioni consente di garantire la stabilità delle applicazioni.
In questo esercizio si inizierà con un'applicazione di esempio che include una potenziale condizione di errore all'interno di un metodo denominato. Il metodo aggiornato genererà throw un'eccezione quando rileva il problema. L'eccezione verrà gestita in un catch blocco del codice che chiama il metodo . Il risultato è un'applicazione che offre un'esperienza utente migliore.
Creare un nuovo progetto di codice
Il primo passaggio consiste nel creare un progetto di codice che è possibile usare durante questo modulo.
Aprire una nuova istanza di Visual Studio Code.
Nel menu File selezionare Apri cartella.
Nella finestra di dialogo Apri cartella passare alla cartella Desktop di Windows.
Nella finestra di dialogo Apri cartella selezionare Nuova cartella.
Assegnare alla nuova cartella il nome ThrowExceptions101 e quindi selezionare Seleziona cartella.
Dal menu Terminale scegliere Nuovo terminale.
Userai un comando CLI di .NET per creare una nuova applicazione console.
Al prompt dei comandi del pannello TERMINAL immettere il comando seguente:
dotnet new consoleChiudere il pannello TERMINALE.
Esaminare un'applicazione di esempio
Usare la procedura seguente per caricare ed esaminare un'applicazione di esempio.
Aprire il file Program.cs.
Nel menu Visualizza selezionare Riquadro comandi.
Al prompt dei comandi immettere .net: g e quindi selezionare .NET: Generare asset per la compilazione e il debug.
Sostituire il contenuto del file Program.cs con il codice seguente:
// 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; }Prenditi un minuto per esaminare il codice.
Si noti che l'applicazione esegue le attività seguenti:
Le istruzioni di primo livello utilizzano
Console.ReadLine()per ottenere valori perlowerBoundeupperBound.Le istruzioni di primo livello passano
lowerBoundeupperBoundcome argomenti quando viene chiamato il metodoAverageOfEvenNumbers.Il metodo
AverageOfEvenNumbersesegue le seguenti attività:- Dichiara le variabili locali usate nei calcoli.
- Usa un
forciclo per sommare i numeri pari tralowerBoundeupperBound. La somma viene archiviata insum. - Conta il numero di numeri inclusi nella somma. Il conteggio viene archiviato in
count. - Archivia la media dei numeri sommati in una variabile denominata
average. Viene restituito il valore diaverage.
Le istruzioni di primo livello stampano sulla console il valore restituito da
AverageOfEvenNumberse poi sospendono l'esecuzione.
Configurare l'ambiente di debug
L'applicazione di esempio legge l'input dell'utente dalla console. Il pannello DEBUG CONSOLE non supporta la lettura dell'input dalla console. È necessario aggiornare il file di launch.json prima di poter eseguire questa applicazione nel debugger.
Usare la visualizzazione EXPLORER per aprire il file launch.json.
Nel file launch.json aggiornare l'attributo
consolenel modo seguente:// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console":"integratedTerminal",Il valore predefinito per l'attributo
consoleèinternalConsole, che è allineato al pannello CONSOLE DI DEBUG. Sfortunatamente, il pannello DEBUG CONSOLE non supporta l'input della console. L'impostazioneintegratedTerminalè allineata al pannello TERMINALE, che supporta l'input e l'output della console.Salvare le modifiche apportate al file launch.json e quindi chiudere il file.
Nel menu Esegui di Visual Studio Code selezionare Avvia debug.
Passare al pannello TERMINALE.
Al prompt "limite inferiore", immettere 3
Al prompt "limite superiore" immettere 11
Si noti che l'applicazione visualizza il messaggio seguente e quindi sospende:
The average of even numbers between 3 and 11 is 7.Per uscire dall'applicazione, premere INVIO.
Generare un'eccezione nel metodo AverageOfEvenNumbers
Il AverageOfEvenNumbers metodo prevede un limite superiore maggiore del limite inferiore. Si verifica un DivideByZero errore se il limite inferiore è maggiore o uguale al limite superiore.
È necessario aggiornare il AverageOfEvenNumbers metodo per generare un'eccezione quando il limite inferiore è maggiore o uguale al limite superiore.
Prendere in considerazione il modo in cui si vuole risolvere il problema.
Un'opzione consiste nell’eseguire il wrapping del calcolo di
averageall'interno di un blocco di codicetryed eseguirecatchdell'eccezioneDivideByZeroquando si verifica. È possibile rigenerare l'eccezione e gestirla nel codice di chiamata.Un'altra opzione consiste nel valutare i parametri di input prima di avviare i calcoli. Se
lowerBoundè maggiore o uguale aupperBound, è possibile generare un'eccezione.La valutazione dei parametri e la generazione di un'eccezione prima di avviare i calcoli è la scelta migliore.
Considerare il tipo di eccezione da generare.
Esistono due tipi di eccezione allineati al problema:
ArgumentOutOfRangeException- UnArgumentOutOfRangeExceptiontipo di eccezione deve essere generato solo quando il valore di un argomento non è compreso nell'intervallo consentito di valori come definito dal metodo richiamato. Anche seAverageOfEvenNumbersnon definisce in modo esplicito un intervallo consentito perlowerBoundoupperBound, il valore dilowerBoundimplica l'intervallo consentito perupperBound.InvalidOperationExceptionInvalidOperationException: un tipo di eccezione deve essere generato solo quando le condizioni operative di un metodo non supportano il completamento di una determinata chiamata al metodo. In questo caso, le condizioni operative vengono stabilite dai parametri di input del metodo .
Quando sono disponibili due o più tipi di eccezione tra cui scegliere, selezionare il tipo di eccezione più adatto al problema. In questo caso, i due tipi di eccezione sono allineati alla questione in ugual misura.
Quando si dispone di due o più tipi di eccezione allineati allo stesso modo del problema, selezionare il tipo di eccezione con ambito più ristretto. Il tipo di eccezione
ArgumentOutOfRangeExceptionè limitato agli argomenti passati al metodo. IlInvalidOperationExceptiontipo di eccezione ha come ambito le condizioni operative del metodo . In questo caso, ilArgumentOutOfRangeExceptiontipo di eccezione è più limitato rispetto alInvalidOperationExceptiontipo di eccezione.Il
AverageOfEvenNumbersmetodo deve generare un'eccezioneArgumentOutOfRangeException.Nella parte superiore del metodo
AverageOfEvenNumbers, per rilevare il problema del limite superiore, aggiornare il codice come indicato di seguito:if (lowerBound >= upperBound) { } int sum = 0;Per creare e generare un'eccezione
ArgumentOutOfRangeException, aggiornare il blocco di codiceifnel modo seguente:if (lowerBound >= upperBound) { throw new ArgumentOutOfRangeException("upperBound", "ArgumentOutOfRangeException: upper bound must be greater than lower bound."); }Questa riga di codice inizializza una nuova istanza della
ArgumentOutOfRangeExceptionclasse con il nome del parametro di input che causa l'eccezione e un messaggio di errore specificato.
Rilevare l'eccezione nel codice di chiamata
Quando possibile, le eccezioni devono essere rilevate a livello di stack di chiamate in cui possono essere gestite. In questa applicazione di esempio i parametri del AverageOfEvenNumbers metodo possono essere gestiti nel metodo chiamante (istruzioni di primo livello).
Scorrere verso l'alto fino alle istruzioni di primo livello.
Per racchiudere la chiamata al metodo
AverageOfEvenNumberse l'istruzioneConsole.WriteLineall'interno di un blocco di codicetry, aggiornare il codice nel modo seguente: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}."); }Per creare la clausola associata
catch, immettere il codice seguente:catch(ArgumentOutOfRangeException ex) { }Prendere in considerazione il modo in cui è possibile gestire l'eccezione.
Per gestire questa eccezione, il codice deve eseguire le operazioni seguenti:
- Spiegare il problema all'utente.
- Ottenere un nuovo valore per
upperBound. - Chiama
AverageOfEvenNumbersusando il nuovoupperBound. - Proseguire l'eccezione con
catchse il nuovoupperBoundfornito è ancora minore o uguale alowerBound.
Per continuare a implementare
catchper l'eccezione, è necessario un ciclo. Poiché si vuole chiamare ilAverageOfEvenNumbersmetodo almeno una volta, deve essere usato undociclo.Per racchiudere i blocchi
tryecatchall'interno di un ciclodo, aggiorna il codice come segue: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) { } }Per definire la condizione di uscita di un ciclo di
while, è necessaria un'espressionedo. È difficile specificare la condizione prima che venga definito il contenuto deldoblocco di codice. Il completamento delcatchblocco di codice consentirà di definire l'espressionewhilenecessaria.Per spiegare il problema all'utente e ottenere un nuovo
upperBound, aggiornare ilcatchblocco di codice nel modo seguente: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()); }Il blocco di codice aggiornato
catchdescrive il problema e richiede all'utente di immettere un nuovo limite superiore. Tuttavia, cosa accade se l'utente non ha un valore limite superiore valido da immettere? Cosa accade se l'utente deve uscire dal ciclo anziché immettere un valore?Per fornire all'utente un'opzione per uscire dal ciclo anziché immettere un nuovo limite superiore, aggiornare il
catchblocco di codice come indicato di seguito: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); } }Il blocco di codice aggiornato
catchinclude due percorsi, un percorso "exit" e un percorso "nuovo limite superiore".Prenditi un minuto per considerare l'espressione
whilenecessaria per il ciclodo.Se l'utente immette "Exit" al prompt, il codice deve uscire dal ciclo. Se l'utente immette un nuovo limite superiore, il ciclo deve continuare. È
whilepossibile utilizzare un'espressione che valuta un valore booleano. Per esempio:while (exit == false);L'espressione proposta
whilestabilirà il comportamento seguente:- Il
dociclo continuerà a scorrere finché il valore booleanoexitè uguale afalse. - Il ciclo interromperà l'iterazione
donon appena il valore booleanoexitè uguale atrue.
- Il
Per creare un'istanza di una variabile booleana denominata
exite usareexitper impostare la condizione di uscita deldociclo, aggiornare il codice nel modo seguente: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);Salvare il codice aggiornato.
Nel menu Esegui selezionare Avvia debug.
Passare al pannello TERMINALE.
Al prompt "limite inferiore", immettere 3
Al prompt "limite superiore" immettere 3
Si noti che l'output seguente viene visualizzato nel pannello TERMINALE:
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):Alla richiesta di un nuovo limite superiore, immettere 11
Si noti che l'output seguente viene visualizzato nel pannello TERMINALE:
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.Per uscire dall'applicazione, premere INVIO.
Congratulazioni! È stata generata, rilevata e gestita un'eccezione.
Riepilogo
Ecco i concetti più importanti di questa unità da ricordare:
- Assicurarsi che l'ambiente di debug sia configurato per supportare i requisiti dell'applicazione.
- Il codice del metodo deve generare un'eccezione quando viene rilevato un problema o una condizione.
- Le eccezioni devono essere rilevate a un livello nello stack di chiamate in cui possono essere risolte.