練習:建立和擲回例外狀況
開發人員通常需要在方法內建立並拋出例外狀況,然後在呼叫堆疊中較深的位置攔截並處理這些例外狀況。 例外狀況處理可協助您確保應用程式的穩定性。
在本練習中,您將從範例應用程式開始,其中包含呼叫方法內的潛在錯誤狀況。 當您的更新方法偵測到問題時,將會 throw 引發例外。 例外狀況將會在呼叫 方法的程式代碼區塊中 catch 處理。 結果是提供更佳用戶體驗的應用程式。
建立新的程式代碼專案
第一個步驟是建立可在本課程模組期間使用的程式代碼專案。
開啟新的 Visual Studio Code 執行個體。
在 [檔案] 功能表上,選取 [開啟資料夾]。
在 [ 開啟資料夾] 對話框中,流覽至您的 Windows Desktop 資料夾。
在 [ 開啟資料夾] 對話框中,選取 [ 新增資料夾]。
將新資料夾命名為 ThrowExceptions101,然後選取 [ 選取資料夾]。
在 [終端機] 功能表上,選取 [新增終端機]。
您將使用 .NET CLI 命令來建立新的控制台應用程式。
在終端機面板命令提示字元中,輸入下列命令:
dotnet new console關閉終端面板。
檢閱範例應用程式
使用下列步驟來載入和檢閱範例應用程式。
開啟 Program.cs 檔案。
在 [檢視] 功能表上,選取 [命令選擇區]。
在命令提示字元中,輸入 .net:g ,然後選取 [.NET]:產生用於建置和偵錯的資產。
使用下列程式碼取代 Program.cs 檔案的內容:
// 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; }花一分鐘的時間檢閱程序代碼。
請注意,應用程式會執行下列工作:
最上層語句會使用
Console.ReadLine()語句來取得lowerBound和upperBound的值。最上層語句在呼叫
lowerBound方法時,會傳遞upperBound和AverageOfEvenNumbers作為參數。方法
AverageOfEvenNumbers會執行下列工作:- 宣告計算中使用的局部變數。
- 使用
for迴圈來計算lowerBound和upperBound之間的偶數總和。 總和會儲存在 中sum。 - 計算總和中包含的數位數目。 計數會儲存在 中
count。 - 將加總數位的平均值儲存在名為
average的變數中。 傳回的值是average。
最上層語句會將 傳
AverageOfEvenNumbers回的值列印至主控台,然後暫停執行。
設定偵錯環境
範例應用程式會從主控台讀取使用者輸入。 [偵錯主控台] 面板不支援從主控台讀取輸入。 您必須先更新 launch.json 檔案,才能在調試程式中執行此應用程式。
使用 EXPLORER 檢視來開啟 launch.json 檔案。
在 launch.json 檔案中,更新
console屬性,如下所示:// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console":"integratedTerminal",console屬性的預設值為internalConsole,對齊於偵錯主控台面板。 不幸的是,[偵錯控制台] 面板不支援主控台輸入。 此integratedTerminal設定會對齊支援主控台輸入和輸出的 [終端機] 面板。將變更儲存至 launch.json 檔案,然後關閉檔案。
在 Visual Studio Code 上,[執行] 功能表,選取 [開始偵錯]。
切換至 [終端機] 面板。
在 [下限] 提示字元中,輸入 3
在 [上限] 提示字元中,輸入 11
請注意,應用程式會顯示下列訊息,然後暫停:
The average of even numbers between 3 and 11 is 7.若要結束應用程式,請按 Enter。
在 AverageOfEvenNumbers 方法中拋出例外
方法 AverageOfEvenNumbers 預期上限大於下限。 DivideByZero如果下限大於或等於上限,就會發生錯誤。
當下限大於或等於上限時,您必須更新 AverageOfEvenNumbers 方法,以擲回例外狀況。
請花一分鐘時間來考慮您要如何處理問題。
其中一個選項是將
average的計算包裝在try程式碼區塊內,並在發生例外狀況時catchDivideByZero。 您可以重新擲回例外狀況,然後在呼叫的程式碼中加以處理。另一個選項是在開始計算之前評估輸入參數。 如果
lowerBound大於或等於upperBound,您可以擲回例外狀況。在開始計算之前評估參數並擲回例外狀況是較佳的選擇。
請考慮要擲回的例外狀況類型。
有兩種與問題相符的例外狀況類型:
ArgumentOutOfRangeExceptionArgumentOutOfRangeException- 只有當自變數的值超出叫用方法所定義的允許值範圍之外時,才應該擲回例外狀況類型。 雖然AverageOfEvenNumbers未明確定義lowerBound和upperBound的允許範圍,但lowerBound的值確實暗示了upperBound的允許範圍。InvalidOperationExceptionInvalidOperationException:只有在方法的作業條件不支援特定方法呼叫成功完成時,才應該擲回例外狀況類型。 在此情況下,作業條件是由 方法的輸入參數所建立。
當您有兩個以上的例外狀況類型可供選擇時,請選取更貼近問題的例外狀況類型。 在此情況下,這兩個例外狀況類型會與問題一致。
當您有兩個或多個符合問題的例外狀況類型時,請選取範圍最窄的例外狀況類型。
ArgumentOutOfRangeException例外狀況類型的範圍是傳遞至方法的引數。InvalidOperationException例外狀況類型是依照方法的運作條件而定。 在此情況下,ArgumentOutOfRangeException例外狀況類型的範圍會比InvalidOperationException例外狀況類型更窄。方法
AverageOfEvenNumbers應該會擲回ArgumentOutOfRangeException例外狀況。在
AverageOfEvenNumbers方法的頂端,若要偵測上限問題,請更新您的程式碼,如下所示:if (lowerBound >= upperBound) { } int sum = 0;若要建立並擲回
ArgumentOutOfRangeException例外狀況,請更新if程式碼區塊,如下所示:if (lowerBound >= upperBound) { throw new ArgumentOutOfRangeException("upperBound", "ArgumentOutOfRangeException: upper bound must be greater than lower bound."); }此程式代碼行會初始化類別
ArgumentOutOfRangeException的新實例,使用導致例外狀況的輸入參數名稱以及指定的錯誤訊息。
捕捉呼叫代碼中的例外狀況
盡可能在可以處理的呼叫堆疊層級攔截例外狀況。 在此範例應用程式中,方法的參數 AverageOfEvenNumbers 可以在呼叫方法中管理(最上層語句)。
向上捲動至最上層陳述式。
若要將
AverageOfEvenNumbers方法呼叫和Console.WriteLine語句括在try程式區塊中,請按如下更新您的程式碼。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子句,請輸入下列程序代碼:catch(ArgumentOutOfRangeException ex) { }請花一分鐘時間考慮如何處理例外狀況。
若要處理此例外狀況,您的程式代碼必須執行下列動作:
- 向使用者說明問題。
- 為
upperBound獲取一個新值。 - 使用新的
AverageOfEvenNumbers來呼叫upperBound。 - 如果提供的新
catch仍然小於或等於upperBound,請繼續執行lowerBound例外狀況。
繼續處理
catch這個例外狀況需要使用迴圈。 由於您想要至少呼叫AverageOfEvenNumbers方法一次,因此應該使用do迴圈。若要將
try和catch區塊包在do迴圈內,請按以下方式更新您的程式碼: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) { } }要定義
while循環的退出條件,需要一個do表達式。 在定義程式代碼區塊的內容do之前,很難指定條件。 完成程式catch代碼區塊可協助您定義while所需的表達式。若要向使用者說明問題並取得新的
upperBound,請更新您的程式catch代碼區塊,如下所示: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()); }更新
catch的程式代碼區塊描述問題,並要求使用者輸入新的上限。 不過,如果用戶沒有有效的上限值可輸入,該怎麼辦? 如果使用者需要結束迴圈,而不是輸入值,該怎麼辦?若要提供使用者結束循環的選項,而不是輸入新的上限,請更新您的程式
catch代碼區塊,如下所示: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); } }更新的
catch程式碼區塊包含兩個路徑: 一個「結束」路徑和「新的上限」路徑。請花一分鐘來思考
while迴圈需要的do表達式。如果使用者在提示字元中輸入 「結束」,程式代碼應該會結束迴圈。 如果使用者輸入新的上限,迴圈應該會繼續。
while一個用於評估布爾值的表達式可以被使用。 例如:while (exit == false);建議的
while表達式將會建立下列行為:- 迴圈
do只要布爾值exit等於false就會繼續迭代。 - 迴圈
do會在布爾值exit等於true時立即停止反覆執行。
- 迴圈
若要具現化名為
exit的布爾變數,並使用exit來設定循環的do結束條件,請更新您的程序代碼,如下所示: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);儲存更新的程序代碼。
在 [執行] 功能表上,選取 [開始偵錯]。
切換至 [終端機] 面板。
在 [下限] 提示字元中,輸入 3
在「上限」提示中,輸入 3
請注意,終端機面板中會顯示下列輸出:
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
請注意,終端機面板中會顯示下列輸出:
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.若要結束應用程式,請按 Enter。
祝賀! 您已成功擲回、攔截並處理例外狀況。
回顧
以下為本單元須記住的一些重點:
- 請確定您的偵錯環境已設定為支援您的應用程式需求。
- 偵測到問題或條件時,方法程式代碼應該擲回例外狀況。
- 例外狀況應該在可解析的呼叫堆疊層級攔截。