แนวทางปฏิบัติที่ดีที่สุดในการจัดการข้อยกเว้นใน C #

การจัดการข้อยกเว้นเป็นเทคนิคในการจัดการข้อผิดพลาดรันไทม์ในโค้ดแอปพลิเคชันของคุณ โดยทั่วไปคุณมีข้อยกเว้นสองประเภท: ข้อยกเว้นที่สร้างขึ้นโดยแอปพลิเคชันและประเภทที่สร้างขึ้นโดยรันไทม์ ข้อยกเว้นควรได้รับการจัดการด้วยความระมัดระวัง - คุณควรมีความคิดที่ดีว่าควรจัดการข้อยกเว้นอย่างไรและเมื่อใดจึงจำเป็นต้องจัดการในโค้ดของคุณ ในโพสต์นี้ฉันจะนำเสนอเคล็ดลับและแนวทางปฏิบัติที่ดีที่สุดในการทำงานกับข้อยกเว้นใน C #

คลาสพื้นฐานสำหรับข้อยกเว้นทั้งหมดใน. NET คือ Exception คลาสข้อยกเว้นทั้งหมดในลำดับชั้นของข้อยกเว้นได้มาจากคลาสนี้โดยตรงหรือโดยอ้อม คลาส ApplicationException และ SystemException ได้มาจากคลาส Exception Common Language Runtime (CLR) พ่นอินสแตนซ์ของชนิดที่ได้มาจาก SystemException เมื่อเกิดข้อผิดพลาดที่รันไทม์ โปรดทราบว่าคุณไม่ควรจับ SystemException หรือโยนอินสแตนซ์ของ SystemException ในโค้ดของแอปพลิเคชันของคุณ

เมื่อสร้างคลาสข้อยกเว้นแบบกำหนดเองให้รับมาจากคลาส Exception เสมอไม่ใช่จากคลาส ApplicationException หนึ่งในเหตุผลนี้คืออินสแตนซ์ของ ApplicationException ถูกส่งโดยแอ็พพลิเคชันและไม่เคยเกิดจากรันไทม์ ในการเพิ่ม ApplicationException ในโค้ดของคุณคุณก็แค่เพิ่ม call stack โดยไม่ต้องเพิ่มมูลค่ามากนัก

เป็นแนวทางการออกแบบที่ไม่ดีในการใช้การจัดการข้อยกเว้นเพื่อส่งคืนข้อมูลจากวิธีการ หากคุณส่งคืนข้อมูลข้อยกเว้นจากวิธีการของคุณการออกแบบชั้นเรียนของคุณไม่ถูกต้องและควรได้รับการตรวจซ้ำ โปรดทราบว่าข้อยกเว้นจะเพิ่มขึ้นจนถึงระดับที่สูงขึ้นในลำดับชั้นการเรียกเมธอดและไม่ใช่แนวทางปฏิบัติที่ดีในการจัดการข้อยกเว้นในทุกเลเยอร์ของแอปพลิเคชันของคุณ คุณควรจัดการข้อยกเว้นให้สูงขึ้นในลำดับชั้นการโทรมากที่สุดเท่าที่จะทำได้คุณสามารถใช้ข้อยกเว้นในเลเยอร์การนำเสนอและแสดงข้อความที่เหมาะสมแก่ผู้ใช้เพื่อแจ้งข้อผิดพลาดที่เกิดขึ้น

จำเป็นต้องโยนข้อยกเว้นอีกครั้งเมื่อคุณต้องการย้อนกลับธุรกรรมฐานข้อมูล เป็นแนวทางปฏิบัติที่ดีในการใช้ข้อยกเว้นเฉพาะเช่น FileNotFoundException, IOException และอื่น ๆ เมื่อเขียนตัวจัดการข้อยกเว้นจากนั้นบล็อก catch ทั่วไปในตอนท้ายด้วยคลาส Exception เพื่อให้แน่ใจว่าคุณได้รับทราบข้อผิดพลาดที่แน่นอนหรือข้อผิดพลาดเฉพาะที่เกิดขึ้น MSDN ระบุ: "คลาส ApplicationException ไม่ได้ให้ข้อมูลเกี่ยวกับสาเหตุของข้อยกเว้นในสถานการณ์ส่วนใหญ่ไม่ควรโยนอินสแตนซ์ของคลาสนี้ในกรณีที่คลาสนี้เป็นอินสแตนซ์ข้อความที่มนุษย์อ่านได้ซึ่งอธิบายข้อผิดพลาดควรเป็น ส่งต่อไปยังผู้สร้าง "

คุณควรใช้บล็อก try - catch เพื่อจัดการข้อยกเว้นและใช้บล็อกสุดท้ายเพื่อล้างทรัพยากรที่ใช้ในโปรแกรมของคุณ บล็อกการลองจะมีรหัสที่อาจทำให้เกิดข้อยกเว้นขึ้นบล็อกการจับจะถูกใช้เพื่อจัดการกับข้อยกเว้นที่เกิดขึ้นภายในบล็อกลองและสุดท้ายจะใช้บล็อกเพื่อยกเลิกการจัดสรรทรัพยากรใด ๆ ที่โปรแกรมใช้ โปรดทราบว่าการบล็อกในที่สุดรับประกันว่าจะดำเนินการโดยไม่คำนึงว่าจะมีข้อยกเว้นเกิดขึ้นหรือไม่ ดังนั้นสุดท้ายบล็อกจึงเป็นสถานที่ที่ดีที่สุดในโค้ดของคุณสำหรับการล้างทรัพยากรที่โปรแกรมของคุณใช้

ข้อมูลโค้ดด้านล่างแสดงวิธีใช้คำสั่ง "ใช้" เพื่อทิ้งทรัพยากร โปรดทราบว่าคำสั่ง "ใช้" เทียบเท่ากับ try - สุดท้ายบล็อก

public string Read(string fileName)

{

try

{

string data;

using (StreamReader streamReader = new StreamReader(fileName))

{

data = streamReader.ReadToEnd();

}

return data;

}

catch (Exception)

{

throw;

}

}

การโยนข้อยกเว้นมีราคาแพง เป็นแนวทางปฏิบัติที่ไม่ดีในการลบข้อยกเว้น - ในการลบข้อยกเว้นใหม่คุณจะทำให้การติดตามสแต็กหลวม

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

throw ex;

}

ให้ใช้คำสั่ง "throw" แทนหากคุณไม่ต้องการจัดการข้อยกเว้นในตัวจัดการข้อยกเว้นของคุณและเผยแพร่ข้อยกเว้นขึ้นไปในลำดับชั้นการโทร

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

throw;

}

อย่ากลืนข้อยกเว้น - คุณไม่ควรซ่อนข้อผิดพลาดที่เกิดขึ้น เป็นแนวทางปฏิบัติที่ดีในการบันทึกข้อยกเว้นในแอปพลิเคชันของคุณ เมื่อบันทึกข้อยกเว้นคุณควรบันทึกอินสแตนซ์ข้อยกเว้นเสมอเพื่อให้มีการบันทึกการติดตามสแต็กที่สมบูรณ์ไม่ใช่ข้อความยกเว้นเท่านั้น นี่คือตัวอย่างที่แสดงให้เห็นถึงสิ่งนี้

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

LogManager.Log(ex.ToString());

}

คุณไม่ควรใช้ข้อยกเว้นเพื่อเผยแพร่หรือดำเนินการตามกฎทางธุรกิจในแอปพลิเคชันของคุณ คุณสามารถหลีกเลี่ยงข้อยกเว้นในโค้ดของคุณได้โดยใช้ตรรกะการตรวจสอบความถูกต้องที่เหมาะสม ในกรณีส่วนใหญ่ควรหลีกเลี่ยงข้อยกเว้น - คุณควรใช้เมื่อจำเป็นเท่านั้น

คุณสามารถอ้างอิงบทความ MSDN นี้สำหรับข้อมูลเพิ่มเติม