แบบฝึกหัด - สร้างและโยนข้อยกเว้น
นักพัฒนามักจําเป็นต้องสร้างและโยนข้อยกเว้นจากภายในเมธอด จากนั้นจะตรวจจับข้อยกเว้นเหล่านั้นลงในสแตกการโทรที่สามารถจัดการได้ การจัดการข้อยกเว้นช่วยให้คุณมั่นใจถึงความเสถียรของแอปพลิเคชันของคุณ
ในแบบฝึกหัดนี้ คุณจะเริ่มต้นด้วยแอปพลิเคชันตัวอย่างที่มีเงื่อนไขข้อผิดพลาดที่อาจเกิดขึ้นภายในเมธอดที่เรียกว่า วิธีการอัปเดตของคุณจะ throw เกิดข้อยกเว้นเมื่อตรวจพบปัญหา ข้อยกเว้นจะได้รับการจัดการใน catch บล็อกของโค้ดที่เรียกใช้เมธอด ผลลัพธ์คือแอปพลิเคชันที่ให้ประสบการณ์ผู้ใช้ที่ดีขึ้น
สร้างโครงการรหัสใหม่
ขั้นตอนแรกคือการสร้างโครงการรหัสที่คุณสามารถใช้ในระหว่างโมดูลนี้
เปิดอินสแตนซ์ใหม่ของ Visual Studio Code
บนเมนู ไฟล์ เลือก เปิดโฟลเดอร์
ในกล่องโต้ตอบ เปิดโฟลเดอร์ ให้นําทางไปยังโฟลเดอร์ Windows Desktop ของคุณ
บนกล่องโต้ตอบ เปิดโฟลเดอร์ เลือก โฟลเดอร์ใหม่
ตั้งชื่อโฟลเดอร์ใหม่ว่า ThrowExceptions101 จากนั้นเลือก เลือกโฟลเดอร์
บนเมนู เทอร์มินัล ให้เลือก เทอร์มินัลใหม่
คุณจะใช้คําสั่ง .NET CLI เพื่อสร้างแอปคอนโซลใหม่
ที่พรอมต์คําสั่งของแผงเทอร์มินัล ให้ป้อนคําสั่งต่อไปนี้:
dotnet new consoleปิดแผงขั้วต่อ
ตรวจทานแอปพลิเคชันตัวอย่าง
ใช้ขั้นตอนต่อไปนี้เพื่อโหลดและตรวจทานแอปพลิเคชันตัวอย่าง
เปิดไฟล์ Program.cs
บนเมนู มุมมอง ให้เลือก ชุดคําสั่ง
ที่พรอมต์คําสั่ง ให้ป้อน .net: g จากนั้นเลือก .NET: สร้าง Assets สําหรับการสร้างและดีบัก
แทนที่เนื้อหาของไฟล์ 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คอนโซลแล้วหยุดการดําเนินการชั่วคราว
กําหนดค่าดีบักสภาพแวดล้อม
แอปพลิเคชันตัวอย่างจะอ่านข้อมูลป้อนเข้าของผู้ใช้จากคอนโซล แผง DEBUG CONSOLE ไม่สนับสนุนการอ่านข้อมูลป้อนเข้าจากคอนโซล คุณจําเป็นต้องอัปเดตไฟล์ 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ซึ่งสอดคล้องกับแผง DEBUG CONSOLE น่าเสียดายที่แผงคอนโซล DEBUG ไม่สนับสนุนการป้อนข้อมูลของคอนโซล การตั้งค่าintegratedTerminalจะสอดคล้องกับแผง TERMINAL ซึ่งสนับสนุนอินพุตและเอาต์พุตของคอนโซลบันทึกการเปลี่ยนแปลงของคุณไปยังแฟ้ม launch.json แล้วปิดแฟ้ม
บนเมนูเรียกใช้รหัส Visual Studio เลือกเริ่มการดีบัก
สลับไปยังแผงขั้วต่อ
ที่พร้อมท์ "ผูกด้านล่าง" ให้ใส่ 3
ที่พร้อมท์ "bound ด้านบน" ให้ใส่ 11
โปรดสังเกตว่าแอปพลิเคชันจะแสดงข้อความต่อไปนี้จากนั้นหยุดชั่วคราว:
The average of even numbers between 3 and 11 is 7.เมื่อต้องการออกจากแอปพลิเคชัน ให้กด Enter
แสดงข้อยกเว้นในวิธี AverageOfEvenNumbers
เม AverageOfEvenNumbers ธอด คาดว่าจะมีขอบสูงสุดที่มากกว่าขอบต่ําสุด ข้อผิดพลาด DivideByZero เกิดขึ้นถ้าขอบล่างมากกว่าหรือเท่ากับขอบสูงสุด
คุณจําเป็นต้องอัปเดต AverageOfEvenNumbers เมธอด เพื่อแสดงข้อยกเว้นเมื่อขอบด้านล่างมากกว่าหรือเท่ากับขอบสูงสุด
ใช้เวลาสักครู่เพื่อพิจารณาวิธีที่คุณต้องการแก้ไขปัญหา
ตัวเลือกหนึ่งคือการตัดการคํานวณ
averageภายในtryบล็อกรหัสและcatchDivideByZeroข้อยกเว้นเมื่อเกิดขึ้น คุณสามารถเถียงข้อยกเว้น แล้วจัดการได้ในรหัสการโทรตัวเลือกอื่นคือการประเมินพารามิเตอร์อินพุตก่อนที่จะเริ่มการคํานวณ หาก
lowerBoundมากกว่าหรือเท่ากับupperBoundคุณสามารถโยนข้อยกเว้นได้การประเมินพารามิเตอร์และโยนข้อยกเว้นก่อนที่จะเริ่มการคํานวณเป็นตัวเลือกที่ดีกว่า
พิจารณาชนิดข้อยกเว้นที่จะโยน
มีข้อยกเว้นสองชนิดที่สอดคล้องกับปัญหา:
-
ArgumentOutOfRangeException- ควรแสดงArgumentOutOfRangeExceptionชนิดข้อยกเว้นเฉพาะเมื่อค่าของอาร์กิวเมนต์อยู่นอกช่วงค่าที่สามารถอนุญาตได้ตามที่กําหนดโดยวิธีการเรียกใช้ แม้ว่าAverageOfEvenNumbersไม่ได้กําหนดช่วงที่สามารถอนุญาตได้สําหรับlowerBoundหรือupperBoundค่าของlowerBoundจะหมายความถึงช่วงที่อนุญาตสําหรับupperBound -
InvalidOperationException: ควรแสดงInvalidOperationExceptionชนิดข้อยกเว้นเฉพาะเมื่อเงื่อนไขการใช้งานของเมธอดไม่สนับสนุนการเสร็จสิ้นที่สําเร็จของการเรียกเมธอดเฉพาะ ในกรณีนี้ เงื่อนไขการทํางานจะถูกสร้างขึ้นโดยพารามิเตอร์อินพุตของวิธีการ
เมื่อคุณมีชนิดข้อยกเว้นสองชนิดขึ้นไปให้เลือก ให้เลือกชนิดข้อยกเว้นที่เหมาะสมกับปัญหานั้นอย่างใกล้ชิดยิ่งขึ้น ในกรณีนี้ ข้อยกเว้นสองชนิดจะสอดคล้องกับปัญหาดังกล่าว
เมื่อคุณมีข้อยกเว้นสองชนิดหรือมากกว่าที่จัดแนวให้สอดคล้องกับปัญหาเท่าๆ กัน ให้เลือกชนิดข้อยกเว้นที่มีขอบเขตแคบที่สุด ชนิด
ArgumentOutOfRangeExceptionข้อยกเว้นมีขอบเขตไปยังอาร์กิวเมนต์ที่ส่งผ่านไปยังเมธอด ชนิดInvalidOperationExceptionข้อยกเว้นถูกกําหนดขอบเขตสําหรับเงื่อนไขการใช้งานของเมธอด ในกรณีนี้ArgumentOutOfRangeExceptionชนิดข้อยกเว้นมีขอบเขตแคบกว่าInvalidOperationExceptionชนิดข้อยกเว้นเม
AverageOfEvenNumbersธอด ควรแสดงArgumentOutOfRangeExceptionข้อยกเว้น-
ที่ด้านบนของ
AverageOfEvenNumbersวิธีการ หากต้องการตรวจสอบปัญหา bound ด้านบน ให้อัปเดตโค้ดของคุณดังนี้: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
ที่พร้อมท์ "bound ด้านบน" ให้ใส่ 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
ยินดีด้วย! คุณถูกโยน จับได้สําเร็จ และจัดการข้อยกเว้น
สรุป
นี่คือสิ่งสําคัญบางอย่างที่ต้องจําจากหน่วยนี้:
- ตรวจสอบให้แน่ใจว่าได้กําหนดค่าดีบักสภาพแวดล้อมของคุณเพื่อสนับสนุนข้อกําหนดของแอปพลิเคชันของคุณ
- รหัสเมธอด ควรมีข้อยกเว้นเมื่อตรวจพบปัญหาหรือเงื่อนไข
- ควรจับข้อยกเว้นที่ระดับในสแต็คการโทรซึ่งสามารถแก้ไขได้