วิธีใช้ลอง catch สำหรับการจัดการข้อยกเว้นเป็นวิธีปฏิบัติที่ดีที่สุด


201

ในขณะที่รักษารหัสของเพื่อนร่วมงานจากแม้กระทั่งคนที่อ้างว่าเป็นนักพัฒนาอาวุโสฉันมักจะเห็นรหัสต่อไปนี้:

try
{
  //do something
}
catch
{
  //Do nothing
}

หรือบางครั้งพวกเขาเขียนข้อมูลการบันทึกลงในไฟล์บันทึกเช่นtry catchบล็อกต่อไปนี้

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);
}

ฉันแค่สงสัยว่าสิ่งที่พวกเขาทำเป็นแนวปฏิบัติที่ดีที่สุดหรือไม่? มันทำให้ฉันสับสนเพราะในความคิดของฉันผู้ใช้ควรรู้ว่าเกิดอะไรขึ้นกับระบบ

โปรดให้คำแนะนำกับฉัน


128
ตัวอย่าง # 1 คือ 99.999% ของเวลาที่ยอมรับไม่ได้
leppie

22
การแสดงข้อยกเว้นโดยตรงกับผู้ใช้ไม่ใช่ความคิดที่ดีเป็นหลักด้วยเหตุผลสองประการ: 1. ถ้าเป็นผู้ใช้ปกติเขาจะรำคาญข้อความอ่านข้อผิดพลาดที่บอกน้อยมากสำหรับเขา / เธอ 2. ถ้าเขาถูกเรียกว่าแฮ็กเกอร์เขาอาจได้รับข้อมูลที่เป็นประโยชน์ วิธีปฏิบัติที่ดีที่สุดคือ IMO คือบันทึกข้อยกเว้นและแสดงข้อความแสดงข้อผิดพลาดที่เป็นมิตร
Leri

4
@leppie หากมีสิ่งที่ไม่คาดคิดเกิดขึ้น (เช่นNullReferenceหรือArgumentNullไม่ใช่ส่วนหนึ่งของโฟลว์แอปพลิเคชัน) หมายความว่ามีข้อผิดพลาดที่ต้องได้รับการแก้ไขดังนั้นการบันทึกข้อมูลจะช่วยให้ดีบั๊กโค้ดของคุณเร็วขึ้น
Leri

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

12
@ ถึงกันถ้ามันเป็นงานแบทช์ฉันกำลังจับที่ระดับบนสุด (หลัก) เพื่อเข้าสู่ระบบจากนั้นทำการ rethrowing เพื่อตั้งการเตือนว่างานยุติลงอย่างผิดปกติ หากเป็นแอปพลิเคชันบนเว็บฉันจะปล่อยให้บับเบิลการยกเว้นไปยังผู้จัดการทั่วโลกการบันทึกและเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าจอข้อผิดพลาด สถานการณ์กรณีการใช้งานของคุณกำหนดสิ่งที่คุณทำกับข้อยกเว้นนั้นหลังจากที่คุณเข้าสู่ระบบหรือจัดการมัน
Anthony Pegram

คำตอบ:


300

กลยุทธ์การจัดการข้อยกเว้นของฉันคือ:

  • ในการตรวจจับข้อยกเว้นที่ไม่สามารถจัดการได้ทั้งหมดด้วยการเชื่อมต่อกับApplication.ThreadException eventแล้วให้เลือก:

    • สำหรับแอปพลิเคชัน UI: เพื่อแสดงให้ผู้ใช้เห็นด้วยข้อความขอโทษ (winforms)
    • สำหรับแอปพลิเคชันบริการหรือคอนโซล: บันทึกลงในไฟล์ (บริการหรือคอนโซล)

จากนั้นฉันจะใส่โค้ดทุกชิ้นที่เรียกใช้จากภายนอกในtry/catch:

  • เหตุการณ์ทั้งหมดเกิดขึ้นจากโครงสร้างพื้นฐาน Winforms (โหลดคลิกเลือกถูกเปลี่ยน ... )
  • เหตุการณ์ทั้งหมดเกิดขึ้นจากองค์ประกอบของบุคคลที่สาม

จากนั้นฉันใส่ใน 'ลอง / จับ'

  • การดำเนินการทั้งหมดที่ฉันรู้อาจไม่ทำงานตลอดเวลา (การดำเนินการ IO การคำนวณด้วยการหารศูนย์ที่เป็นไปได้ ... ) ในกรณีเช่นนี้ฉันโยนใหม่ApplicationException("custom message", innerException)เพื่อติดตามสิ่งที่เกิดขึ้นจริง

นอกจากนี้ผมพยายามทำให้ดีที่สุดเพื่อยกเว้นการจัดเรียงอย่างถูกต้อง มีข้อยกเว้นที่:

  • ต้องแสดงต่อผู้ใช้ทันที
  • ต้องมีการประมวลผลพิเศษเพื่อรวมสิ่งต่างๆเข้าด้วยกันเมื่อเกิดขึ้นเพื่อหลีกเลี่ยงปัญหาการเรียงซ้อน (เช่น: ใส่. EndDate ในfinallyส่วนระหว่างการTreeViewเติม)
  • ผู้ใช้ไม่สนใจ แต่สิ่งสำคัญคือต้องรู้ว่าเกิดอะไรขึ้น ดังนั้นฉันมักจะบันทึกพวกเขา:

    • ในบันทึกเหตุการณ์
    • หรือในไฟล์. log บนดิสก์

เป็นวิธีปฏิบัติที่ดีในการออกแบบวิธีคงที่เพื่อจัดการข้อยกเว้นในตัวจัดการข้อผิดพลาดระดับบนสุดของแอปพลิเคชัน

ฉันยังบังคับให้ตัวเองพยายาม:

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

ดังนั้นในที่สุด:

แย่:

// DON'T DO THIS, ITS BAD
try
{
    ...
}
catch 
{
   // only air...
}

ไร้ประโยชน์:

// DONT'T DO THIS, ITS USELESS
try
{
    ...
}
catch(Exception ex)
{
    throw ex;
}

ในที่สุดการลองโดยไม่ต้องจับก็ใช้ได้อย่างสมบูรณ์:

try
{
    listView1.BeginUpdate();

    // If an exception occurs in the following code, then the finally will be executed
    // and the exception will be thrown
    ...
}
finally
{
    // I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURED OR NOT
    listView1.EndUpdate();
}

สิ่งที่ฉันทำที่ระดับบนสุด:

// i.e When the user clicks on a button
try
{
    ...
}
catch(Exception ex)
{
    ex.Log(); // Log exception

    -- OR --

    ex.Log().Display(); // Log exception, then show it to the user with apologies...
}

สิ่งที่ฉันทำในฟังก์ชั่นที่เรียกว่า:

// Calculation module
try
{
    ...
}
catch(Exception ex)
{
    // Add useful information to the exception
    throw new ApplicationException("Something wrong happened in the calculation module :", ex);
}

// IO module
try
{
    ...
}
catch(Exception ex)
{
    throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}

มีสิ่งที่ต้องทำมากมายเกี่ยวกับการจัดการข้อยกเว้น (ข้อยกเว้นที่กำหนดเอง) แต่กฎที่ฉันพยายามระลึกถึงนั้นเพียงพอสำหรับแอพพลิเคชั่นที่เรียบง่ายที่ฉันทำ

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

// Usage:

try
{
    // boom
}
catch(Exception ex)
{
    // Only log exception
    ex.Log();

    -- OR --

    // Only display exception
    ex.Display();

    -- OR --

    // Log, then display exception
    ex.Log().Display();

    -- OR --

    // Add some user-friendly message to an exception
    new ApplicationException("Unable to calculate !", ex).Log().Display();
}

// Extension methods

internal static Exception Log(this Exception ex)
{
    File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
    return ex;
}

internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
    MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
    return ex;
}

98
catch(Exception ex) { throw ex; }ใน C # นั้นแย่กว่าซ้ำซ้อน (ไม่ว่าคุณจะพิมพ์ประเภทข้อยกเว้นใด) เพื่อ rethrow throw;ใช้ ด้วยอดีตข้อยกเว้นจะดูเหมือนว่ามาจากของคุณthrow exในขณะที่กับหลังมันจะมาจากthrowคำสั่งเดิมอย่างถูกต้อง
CVn

2
ทำไมคุณเบ็ดApplication.ThreadExceptionเหตุการณ์และcatch(Exception ex) {ex.Log(ex);}ห่อยกเว้นกับทุก ฉันอาจจะยอมรับว่าอดีตเป็นแนวปฏิบัติที่ยอดเยี่ยม แต่อย่างหลังเพิ่มความเสี่ยงในการทำซ้ำบันทึกข้อผิดพลาดและซ่อนว่ามีข้อยกเว้นเกิดขึ้น ยังthrow exเป็นเรื่องที่แย่มากมาก
Keith

1
ฉันเข้าใจเกี่ยวกับการจับ (Exception ex) {throw ex; } ไร้ประโยชน์ ดังนั้นฉันคิดว่า "ซ้ำซ้อน" ไม่ใช่คำที่ดีที่สุดในการระบุว่า "อย่าทำอย่างนี้" นั่นเป็นเหตุผลที่ฉันเปลี่ยนโพสต์เล็กน้อยเพื่อให้ดีขึ้นว่าควรหลีกเลี่ยงสองตัวอย่างแรกของลองจับ
Larry

3
คำตอบที่ยอดเยี่ยมและสร้างสรรค์สิ่งที่ฉันชอบคือวลีOnly air :) และขอบคุณสำหรับApplication.ThreadExceptionเหตุการณ์ฉันไม่ทราบว่ามีประโยชน์มาก
Mahdi Tahsildari

4
MSDN แนะนำว่าคุณไม่ควรโยนยกเว้น ApplicationException ในรหัสของคุณ
DavidRR

61

การปฏิบัติที่ดีที่สุดคือการจัดการข้อยกเว้นที่ไม่ควรประเด็นซ่อน ซึ่งหมายความว่าtry-catchบล็อกควรหายากมาก

มี 3 สถานการณ์ที่ใช้วิธีtry-catchทำให้เหมาะสม

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

  2. หากคุณต้องการทำอะไรบางอย่างกับข้อยกเว้น (เช่นการบันทึกหรือย้อนกลับการทำธุรกรรม) จากนั้นโยนข้อยกเว้นอีกครั้ง

  3. จัดการกับข้อยกเว้นที่ไม่รู้จักในระดับสูงที่สุดเท่าที่จะทำได้ - รหัสเดียวที่ควรใช้ข้อยกเว้นและไม่ควรโยนใหม่ควรเป็น UI หรือ API สาธารณะ

สมมติว่าคุณกำลังเชื่อมต่อกับ API ระยะไกลที่นี่คุณจะรู้ว่าเกิดข้อผิดพลาดบางอย่าง (และมีสิ่งต่าง ๆ เกิดขึ้นในสถานการณ์เหล่านั้น) ดังนั้นนี่คือกรณีที่ 1:

try 
{
    remoteApi.Connect()
}
catch(ApiConnectionSecurityException ex) 
{
    // User's security details have expired
    return false;
}

return true;

โปรดทราบว่าจะไม่มีการยกเว้นอื่น ๆ เนื่องจากไม่คาดว่าจะเกิดขึ้น

ตอนนี้สมมติว่าคุณกำลังพยายามบันทึกบางสิ่งลงในฐานข้อมูล เราต้องย้อนกลับถ้ามันล้มเหลวดังนั้นเราจึงมีกรณีที่ 2:

try
{
    DBConnection.Save();
}
catch
{
    // Roll back the DB changes so they aren't corrupted on ANY exception
    DBConnection.Rollback();

    // Re-throw the exception, it's critical that the user knows that it failed to save
    throw;
}

โปรดทราบว่าเราจะทำการยกเว้นอีกครั้ง - รหัสที่สูงขึ้นยังจำเป็นต้องรู้ว่ามีบางสิ่งผิดพลาด

ในที่สุดเราก็มี UI - ที่นี่เราไม่ต้องการมีข้อยกเว้นที่ไม่สามารถจัดการได้อย่างสมบูรณ์ แต่เราไม่ต้องการซ่อนพวกเขาเช่นกัน ที่นี่เรามีตัวอย่างของกรณีที่ 3:

try
{
    // Do something
}
catch(Exception ex) 
{
    // Log exception for developers
    WriteException2LogFile(ex);

    // Display message to users
    DisplayWarningBox("An error has occurred, please contact support!");
}

อย่างไรก็ตาม API หรือ UI เฟรมเวิร์กส่วนใหญ่มีวิธีทั่วไปในการทำเคส 3 ตัวอย่างเช่น ASP.Net มีหน้าจอข้อผิดพลาดสีเหลืองที่ทิ้งรายละเอียดข้อยกเว้น แต่สามารถแทนที่ด้วยข้อความทั่วไปเพิ่มเติมในสภาพแวดล้อมการใช้งานจริง การปฏิบัติดังกล่าวเป็นวิธีปฏิบัติที่ดีที่สุดเนื่องจากช่วยให้คุณประหยัดรหัสได้มาก แต่เนื่องจากการบันทึกข้อผิดพลาดและการแสดงผลควรเป็นการตัดสินใจกำหนดค่าแทนที่จะใช้รหัสฮาร์ด

ทั้งหมดนี้หมายความว่ากรณีที่ 1 (ข้อยกเว้นที่รู้จัก) และกรณีที่ 3 (การจัดการ UI แบบครั้งเดียว) ทั้งคู่มีรูปแบบที่ดีกว่า (หลีกเลี่ยงข้อผิดพลาดที่คาดไว้หรือข้อผิดพลาดจากมือที่จัดการกับ UI)

แม้กระทั่งกรณีที่ 2 สามารถถูกแทนที่ด้วยรูปแบบที่ดีกว่าเช่นขอบเขตธุรกรรม ( usingบล็อกที่ย้อนกลับธุรกรรมใด ๆ ที่ไม่ได้ทำระหว่างบล็อก) ทำให้ผู้พัฒนายากขึ้นที่จะได้รับรูปแบบการปฏิบัติที่ดีที่สุดผิด

ตัวอย่างเช่นสมมติว่าคุณมีแอพพลิเคชัน ASP.Net ขนาดใหญ่ การบันทึกข้อผิดพลาดสามารถผ่านทางELMAH การแสดงข้อผิดพลาดอาจเป็นข้อมูล YSoD ในพื้นที่และข้อความที่แปลเป็นภาษาท้องถิ่นที่ดีในการผลิต การเชื่อมต่อฐานข้อมูลทั้งหมดสามารถทำได้ผ่านขอบเขตธุรกรรมและusingบล็อก คุณไม่จำเป็นต้องมีtry-catchบล็อกเดียว

TL; DR: วิธีปฏิบัติที่ดีที่สุดคือการไม่ใช้try-catchบล็อกเลย


4
@Jorj คุณควรอ่านโพสต์ทั้งหมดและถ้าคุณยังไม่เห็นด้วยบางทีมันอาจจะมีความคิดสร้างสรรค์มากกว่าที่จะตอบโต้ข้อโต้แย้งที่สนับสนุนของฉันมากกว่าที่จะบอกว่าคุณไม่ชอบข้อสรุปของฉัน มีรูปแบบที่ดีกว่าเกือบทุกครั้งtry-catch- มันมีประโยชน์มากและบางครั้งฉันก็ไม่ได้โต้เถียงว่าคุณไม่ควรใช้มัน แต่ 99% ของเวลามีวิธีที่ดีกว่า
Keith

คำตอบที่ดีที่สุด - เกือบทุกประเภทการพัฒนา. NET มีตัวจัดการบางประเภทที่เหมาะกับการจัดการกับข้อยกเว้นในระดับโลกมากขึ้นทำให้จัดการได้ง่ายขึ้นอย่างต่อเนื่องและทำให้ง่ายขึ้น ในการพัฒนา (ทำไมใครต้องการขุดผ่านล็อกไฟล์สำหรับการติดตามสแต็ค ??) @ Kieth ฉันจะนำ TLDR ของคุณและเพิ่มในตัวอย่างบางส่วนของตัวจัดการทั่วโลก (เช่น ThreadException, Application_Error ฯลฯ ) โดยทั้งหมดหมายความว่าจับข้อผิดพลาดเฉพาะ แต่มันก็บ้าไปห่อวิธีการที่เคยมีในลอง / จับ / log
b_levitt

34

มีข้อยกเว้นที่เป็นข้อผิดพลาดของการปิดกั้น

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

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

งานของคุณในฐานะนักพัฒนาซอฟต์แวร์คือการพยายามป้องกันกรณีพิเศษที่พารามิเตอร์หรือสถานการณ์รันไทม์บางอย่างอาจจบลงด้วยข้อยกเว้น นั่นคือข้อยกเว้นต้องไม่ถูกปิด แต่เหล่านี้จะต้องหลีกเลี่ยง

ตัวอย่างเช่นถ้าคุณรู้ว่าบางจำนวนเต็มป้อนข้อมูลอาจจะมาพร้อมกับรูปแบบที่ไม่ถูกต้องให้ใช้แทนint.TryParse int.Parseมีหลายกรณีที่คุณสามารถทำสิ่งนี้แทนที่จะพูดว่า "ถ้ามันล้มเหลวเพียงแค่โยนข้อยกเว้น"

โยนข้อยกเว้นมีราคาแพง

หากหลังจากทั้งหมดยกเว้นจะโยนแทนการเขียนข้อยกเว้นที่จะบันทึกเมื่อได้รับการโยนหนึ่งของการปฏิบัติที่ดีที่สุดคือการจับมันในโอกาสแรกจัดการข้อยกเว้น ตัวอย่างเช่น:

  • ASP.NET: Global.asax Application_Error
  • อื่น ๆ : เหตุการณ์ AppDomain.FirstChanceException

ท่าทางของฉันคือลอง / จับในท้องถิ่นเหมาะกว่าสำหรับจัดการกรณีพิเศษที่คุณอาจแปลข้อยกเว้นเป็นอีกกรณีหนึ่งหรือเมื่อคุณต้องการ "ปิดเสียง" สำหรับกรณีที่พิเศษมากมากมากและพิเศษมาก (ข้อผิดพลาดของไลบรารี โยนข้อยกเว้นที่ไม่เกี่ยวข้องที่คุณต้องการปิดเสียงเพื่อแก้ไขข้อผิดพลาดทั้งหมด)

สำหรับกรณีที่เหลือ:

  • พยายามหลีกเลี่ยงข้อยกเว้น
  • หากเป็นไปไม่ได้: ตัวจัดการข้อยกเว้นโอกาสแรก
  • หรือใช้มุมมอง PostSharp (AOP)

ตอบกลับ @thewhiteambit ในบางความคิดเห็น ...

@thewhiteambit กล่าวว่า:

ข้อยกเว้นไม่ใช่ข้อผิดพลาดร้ายแรงพวกเขาเป็นข้อยกเว้น! บางครั้งพวกเขาไม่ได้มีข้อผิดพลาด แต่ให้พิจารณาข้อผิดพลาดที่ร้ายแรงคือความเข้าใจที่ผิด ๆ ว่าข้อยกเว้นคืออะไร

ก่อนอื่นข้อยกเว้นไม่สามารถเป็นข้อผิดพลาดได้อย่างไร

  • ไม่มีการเชื่อมต่อฐานข้อมูล => ข้อยกเว้น
  • รูปแบบสตริงไม่ถูกต้องในการแยกวิเคราะห์บางชนิด => ข้อยกเว้น
  • การพยายามแยกวิเคราะห์ JSON และในขณะที่อินพุตไม่ใช่ JSON => ข้อยกเว้น
  • อาร์กิวเมนต์nullในขณะที่วัตถุถูกคาดหวัง => ข้อยกเว้น
  • ห้องสมุดบางแห่งมีข้อผิดพลาด => ส่งข้อยกเว้นที่ไม่คาดคิด
  • มีการเชื่อมต่อซ็อกเก็ตและจะถูกตัดการเชื่อมต่อ จากนั้นคุณลองส่งข้อความ => ข้อยกเว้น
  • ...

เราอาจแสดงรายการ 1 พันกรณีเมื่อมีข้อผิดพลาดเกิดขึ้นและหลังจากนั้นทุกกรณีที่เป็นไปได้จะเป็นข้อผิดพลาด

ข้อยกเว้นคือข้อผิดพลาดเนื่องจากในตอนท้ายของวันเป็นวัตถุที่รวบรวมข้อมูลการวินิจฉัย - มีข้อความและเกิดขึ้นเมื่อมีบางสิ่งผิดปกติ

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

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

[... ] พิจารณาข้อผิดพลาดที่ร้ายแรงคือความเข้าใจผิดอย่างสมบูรณ์เกี่ยวกับข้อยกเว้น

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

คำตอบเพิ่มเติมเกี่ยวกับ @thewhiteambit กังวล

ตัวอย่างเช่นในกรณีที่การเชื่อมต่อฐานข้อมูลหายไปโปรแกรมสามารถทำการเขียนต่อไปยังไฟล์โลคัลและส่งการเปลี่ยนแปลงไปยังฐานข้อมูลเมื่อมันพร้อมใช้งานอีกครั้ง String-To-Number ที่ไม่ถูกต้องของคุณอาจพยายามแยกวิเคราะห์อีกครั้งด้วยการตีความภาษาท้องถิ่นในข้อยกเว้นเช่นเมื่อคุณลองภาษาอังกฤษเริ่มต้นเพื่อแยกวิเคราะห์ ("1,5") ล้มเหลวและคุณลองด้วยการแปลภาษาเยอรมันอีกครั้ง ดีเพราะเราใช้เครื่องหมายจุลภาคแทนจุดเป็นตัวคั่น คุณเห็นข้อยกเว้นเหล่านี้จะต้องไม่ปิดกั้น แต่จะต้องจัดการข้อยกเว้นบางอย่างเท่านั้น

  1. หากแอปของคุณอาจทำงานออฟไลน์โดยไม่มีข้อมูลอยู่ในฐานข้อมูลคุณไม่ควรใช้ข้อยกเว้นเนื่องจากการนำโฟลว์ควบคุมไปใช้โดยtry/catchถือเป็นรูปแบบการต่อต้าน งานออฟไลน์เป็นกรณีการใช้งานที่เป็นไปได้ดังนั้นคุณจึงใช้ขั้นตอนการควบคุมเพื่อตรวจสอบว่าฐานข้อมูลสามารถเข้าถึงได้หรือไม่คุณไม่ต้องรอจนกว่าจะไม่สามารถเข้าถึงได้

  2. แยกสิ่งนี้ยังมีกรณีที่คาดว่า ( ไม่ EXCEPTIONAL CASE ) หากคุณคาดหวังสิ่งนี้คุณจะไม่ใช้ข้อยกเว้นเพื่อควบคุมโฟลว์! . คุณได้รับข้อมูลเมตาจากผู้ใช้เพื่อทราบว่าวัฒนธรรมของเขา / เธอคืออะไรและคุณใช้ตัวจัดรูปแบบสำหรับสิ่งนี้! .NET สนับสนุนนี้และสภาพแวดล้อมอื่น ๆ มากเกินไปและข้อยกเว้นเพราะจำนวนการจัดรูปแบบจะต้องหลีกเลี่ยงถ้าคุณคาดว่าจะมีการใช้งานวัฒนธรรมที่เฉพาะเจาะจงของแอพลิเคชัน

ข้อยกเว้นที่ไม่สามารถจัดการได้มักจะกลายเป็นข้อผิดพลาด แต่ข้อยกเว้นนั้นไม่ใช่ codeproject.com/Articles/15921/Not-All-Exceptions-Are-Errors

บทความนี้เป็นเพียงความคิดเห็นหรือมุมมองของผู้เขียน

เนื่องจาก Wikipedia สามารถเป็นเพียงความเห็นของผู้เขียนบทความฉันจะไม่พูดว่ามันเป็นความเชื่อแต่ตรวจสอบสิ่งที่การเข้ารหัสโดยบทความยกเว้นกล่าวว่าบางแห่งในย่อหน้า:

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

มันยังบอกว่าบางแห่ง:

การใช้ข้อยกเว้นไม่ถูกต้อง

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

สุจริตฉันเชื่อว่าซอฟต์แวร์ที่ไม่สามารถพัฒนาไม่ได้ใช้กรณีอย่างจริงจัง ถ้าคุณรู้ว่า ...

  • ฐานข้อมูลของคุณสามารถออฟไลน์ ...
  • ไฟล์บางไฟล์สามารถถูกล็อค ...
  • การจัดรูปแบบบางอย่างอาจไม่รองรับ ...
  • การตรวจสอบโดเมนบางอย่างอาจล้มเหลว ...
  • แอปของคุณควรทำงานในโหมดออฟไลน์ ...
  • สิ่งที่ใช้กรณี ...

... คุณจะไม่ใช้ข้อยกเว้นสำหรับสิ่งนั้น คุณจะรองรับกรณีการใช้งานเหล่านี้โดยใช้โฟลว์ควบคุมปกติ

และถ้าบางกรณีการใช้งานที่ไม่คาดคิดจะไม่ครอบคลุมถึงรหัสของคุณจะล้มเหลวอย่างรวดเร็วเพราะมันจะโยนข้อยกเว้น ขวาเพราะข้อยกเว้นเป็นกรณีพิเศษ

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


6

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

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

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


6

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

  • คุณมีความเข้าใจที่ดีว่าเหตุใดข้อยกเว้นอาจถูกส่งออกไปและคุณสามารถใช้การกู้คืนที่เฉพาะเจาะจงเช่นการแจ้งให้ผู้ใช้ป้อนชื่อไฟล์ใหม่เมื่อคุณจับวัตถุ FileNotFoundException

  • คุณสามารถสร้างและโยนข้อยกเว้นใหม่ที่เฉพาะเจาะจงมากขึ้น

int GetInt(int[] array, int index)
{
    try
    {
        return array[index];
    }
    catch(System.IndexOutOfRangeException e)
    {
        throw new System.ArgumentOutOfRangeException(
            "Parameter index is out of range.");
    }
}
  • คุณต้องการจัดการข้อยกเว้นบางส่วนก่อนส่งผ่านเพื่อจัดการเพิ่มเติม ในตัวอย่างต่อไปนี้ catch catch ใช้เพื่อเพิ่มรายการในบันทึกข้อผิดพลาดก่อนที่จะส่งข้อยกเว้นอีกครั้ง
    try
{
    // Try to access a resource.
}
catch (System.UnauthorizedAccessException e)
{
    // Call a custom error logging procedure.
    LogError(e);
    // Re-throw the error.
    throw;     
}

ผมขอแนะนำให้อ่านทั้ง " ข้อยกเว้นและข้อยกเว้นการจัดการ " ส่วนและวิธีปฏิบัติที่ดีที่สุดสำหรับข้อยกเว้น


1

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


1

ด้วยข้อยกเว้นฉันลองทำสิ่งต่อไปนี้:

อันดับแรกฉันรับข้อยกเว้นชนิดพิเศษเช่นการหารด้วยศูนย์การดำเนินการ IO และอื่น ๆ และเขียนโค้ดตามนั้น ตัวอย่างเช่นการหารด้วยศูนย์ขึ้นอยู่กับการพิสูจน์ของค่าที่ฉันสามารถแจ้งเตือนผู้ใช้ (ตัวอย่างเครื่องคิดเลขอย่างง่ายในการคำนวณระดับกลาง มันและดำเนินการต่อ

จากนั้นฉันพยายามจับข้อยกเว้นที่เหลือและบันทึกไว้ หากเป็นไปได้อนุญาตให้เรียกใช้รหัสมิฉะนั้นแจ้งเตือนผู้ใช้ว่ามีข้อผิดพลาดเกิดขึ้นและขอให้พวกเขาส่งรายงานข้อผิดพลาดทางไปรษณีย์

ในรหัสบางสิ่งเช่นนี้:

try{
    //Some code here
}
catch(DivideByZeroException dz){
    AlerUserDivideByZerohappened();
}
catch(Exception e){
    treatGeneralException(e);
}
finally{
    //if a IO operation here i close the hanging handlers for example
}

1
หารด้วยข้อยกเว้นศูนย์และชอบที่จะได้รับไพ่ที่ดีขึ้นด้วยโดยการตรวจสอบหาเศษก่อนมากกว่า0 try-catchทำไมถึงจับคนทั่วไปExceptionที่นี่? คุณควรปล่อยให้ฟองสบู่เกิดข้อผิดพลาดมากกว่าจัดการที่นี่ในทุกกรณีที่คุณไม่คาดหวัง
Keith

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

ไม่มีแอปที่ควรเคยรักษาข้อยกเว้นอย่างเงียบ ๆ ในบางครั้งคุณมีข้อยกเว้นที่รหัสสามารถจัดการได้ แต่การใช้งานดังกล่าวควรเป็นทั้งของหายากและเฉพาะสำหรับข้อยกเว้นที่คาดไว้ ตัวอย่างของเว็บเซิร์ฟเวอร์ของคุณน่าสงสาร - ควรมีการตั้งค่าการกำหนดค่าที่ให้คุณเลือกวิธีบันทึกข้อผิดพลาดและแสดงว่ามีรายละเอียดหรือหน้า HTTP 500 แต่พวกเขาไม่ควรมองข้ามข้อผิดพลาดในใจ
Keith

ฉันพยายามที่จะเข้าใจว่าอะไรเป็นแรงจูงใจให้ผู้คนเพิ่มคำพ้องความหมายอีกคำสำหรับ "goto" แต่ด้วยความเคารพต่อการหารด้วยศูนย์นี่จะเป็นข้อยกเว้นแบบหนึ่งที่ฉันเห็นได้ว่าปรับการเพิ่มประสิทธิภาพของภาษา ทำไม? เพราะมันอาจเป็นไปได้ว่า A) ศูนย์นั้นมีค่าทางสถิติน้อยที่สุดในชุดข้อมูลของคุณและ B) การใช้ (อนุญาต) ข้อยกเว้นอาจมีประสิทธิภาพมากกว่าเนื่องจากการแบ่งเป็นวิธีหนึ่งในการทดสอบตัวหารศูนย์ เมื่อ A และ B เป็นจริงการดำเนินการโดยเฉลี่ยของโปรแกรมของคุณจะเร็วขึ้นโดยใช้ข้อยกเว้นและอาจมีขนาดเล็กลง
Mike Layton

1

วิธีที่สองเป็นวิธีที่ดี

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

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);//it will write the or log the error in a text file
}

ฉันขอแนะนำให้คุณใช้วิธีที่สองสำหรับการสมัครทั้งหมดของคุณ


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

0

การปล่อยให้บล็อก catch ว่างเปล่าเป็นสิ่งที่แย่กว่านั้น หากมีข้อผิดพลาดวิธีที่ดีที่สุดในการจัดการคือ:

  1. บันทึกลงในไฟล์ \ ฐานข้อมูล ฯลฯ
  2. พยายามแก้ไขทันที (อาจลองวิธีอื่นในการดำเนินการนั้น)
  3. หากเราไม่สามารถแก้ไขได้ให้แจ้งผู้ใช้ว่ามีข้อผิดพลาดบางอย่างและแน่นอนว่ายกเลิกการทำงาน

0

สำหรับฉันการจัดการข้อยกเว้นสามารถเห็นได้ว่าเป็นกฎทางธุรกิจ เห็นได้ชัดว่าวิธีแรกไม่สามารถยอมรับได้ อันที่สองดีกว่าและอาจเป็นวิธีที่ถูกต้อง 100% ถ้าบริบทพูดอย่างนั้น ตัวอย่างเช่นตอนนี้คุณกำลังพัฒนา Outlook Addin หากคุณ addin ส่งข้อยกเว้นที่ไม่สามารถจัดการได้ผู้ใช้ outlook อาจทราบเพราะ Outlook จะไม่ทำลายตัวเองเนื่องจากปลั๊กอินหนึ่งล้มเหลว และคุณมีเวลายากที่จะคิดออกว่าเกิดอะไรขึ้น ดังนั้นวิธีที่สองในกรณีนี้สำหรับฉันมันเป็นวิธีที่ถูกต้อง นอกเหนือจากการบันทึกข้อยกเว้นคุณอาจตัดสินใจแสดงข้อความแสดงข้อผิดพลาดแก่ผู้ใช้ - ฉันถือว่าเป็นกฎธุรกิจ


0

แนวทางปฏิบัติที่ดีที่สุดคือการโยนข้อยกเว้นเมื่อเกิดข้อผิดพลาด เนื่องจากข้อผิดพลาดเกิดขึ้นและไม่ควรซ่อน

แต่ในชีวิตจริงคุณสามารถมีหลายสถานการณ์เมื่อคุณต้องการซ่อนสิ่งนี้

  1. คุณพึ่งพาองค์ประกอบบุคคลที่สามและคุณต้องการดำเนินการโปรแกรมต่อในกรณีที่เกิดข้อผิดพลาด
  2. คุณมีกรณีธุรกิจที่คุณต้องดำเนินการต่อในกรณีที่เกิดข้อผิดพลาด

6
เลขที่ห้ามไม่ได้Exceptionโยน เคย. โยนคลาสย่อยที่เหมาะสมสำหรับExceptionทุกสิ่งที่คุณต้องการ แต่ไม่เคยExceptionเพราะมันไม่มีข้อมูลเชิงความหมาย ฉันแบนออกไม่สามารถเห็นสถานการณ์ที่เหมาะสมที่จะโยนExceptionแต่ไม่ใช่คลาสย่อยของมัน
CVn


0

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

คำสั่งจับควรจับมากขึ้นโดยเฉพาะข้อยกเว้นเช่นFileNotFoundExceptionนั้นที่มากจบคุณควรจับExceptionซึ่งจะจับข้อยกเว้นอื่น ๆ และเข้าสู่ระบบพวกเขา


ทำไมต้องเป็นนายพลcatch(Exception)ในตอนท้าย? หากคุณไม่ได้คาดหวังว่าจะเป็นการดีที่สุดที่จะส่งมันต่อไปยังเลเยอร์ถัดไป
Keith

1
@ Keith ใช่คุณพูดถูก ... ไม่มีข้อยกเว้นใด ๆ ที่คุณไม่ได้คาดหวัง แต่คุณสามารถยกเว้นข้อยกเว้นทั่วไปในการเข้าสู่ระบบ ..
Anirudha

0

บางครั้งคุณต้องจัดการกับข้อยกเว้นที่ไม่พูดอะไรกับผู้ใช้

ทางของฉันคือ:

  • เพื่อตรวจสอบข้อยกเว้นที่ไม่ได้รับการเอาใจใส่ในระดับแอปพลิเคชัน (เช่นใน global.asax) สำหรับข้อยกเว้นที่สำคัญ (แอปพลิเคชันไม่สามารถเป็นประโยชน์ได้) ข้อยกเว้นเหล่านี้ฉันไม่ได้จับในสถานที่ เพียงบันทึกในระดับแอปและให้ระบบทำงานได้
  • จับ "ที่" และแสดงข้อมูลที่เป็นประโยชน์ต่อผู้ใช้ (ป้อนหมายเลขผิดไม่สามารถแยกวิเคราะห์)
  • ทันที่และไม่ทำอะไรเลยกับปัญหาส่วนเพิ่มเช่น "ฉันจะตรวจสอบข้อมูลอัปเดตบนพื้นหลัง แต่บริการไม่ทำงาน"

มันไม่จำเป็นต้องเป็นการปฏิบัติที่ดีที่สุดอย่างแน่นอน ;-)


0

ฉันสามารถบอกคุณบางสิ่ง:

ไม่สามารถยอมรับข้อมูลโค้ด # 1 ได้เนื่องจากไม่สนใจข้อยกเว้น (มันกลืนมันเหมือนไม่มีอะไรเกิดขึ้น)

ดังนั้นอย่าเพิ่ม catch block ที่ไม่ทำอะไรเลยหรือเพียงแค่สร้างใหม่

บล็อก catch ควรเพิ่มค่าบางอย่าง ตัวอย่างเช่นข้อความที่ส่งออกไปยังผู้ใช้หรือข้อผิดพลาดเข้าสู่ระบบ

อย่าใช้ข้อยกเว้นสำหรับตรรกะของโปรแกรมโฟลว์ปกติ ตัวอย่างเช่น:

เช่นการตรวจสอบอินพุต <- นี่เป็นสถานการณ์ที่ไม่ถูกต้อง แต่คุณควรเขียนวิธีIsValid(myInput);การตรวจสอบว่ารายการอินพุตนั้นถูกต้องหรือไม่

รหัสการออกแบบเพื่อหลีกเลี่ยงข้อยกเว้น ตัวอย่างเช่น:

int Parse(string input);

หากเราส่งค่าที่ไม่สามารถแยกวิเคราะห์เป็น int วิธีนี้จะโยนและยกเว้นยกเว้นว่าเราอาจเขียนสิ่งนี้:

bool TryParse(string input,out int result); <- วิธีนี้จะคืนค่าบูลีนเพื่อระบุว่าการแยกวิเคราะห์สำเร็จหรือไม่

อาจจะเป็นบิตออกจากเล็ก ๆ น้อย ๆ ของขอบเขตของคำถามนี้ แต่ฉันหวังว่านี้จะช่วยให้คุณตัดสินใจที่เหมาะสมเมื่อมันเป็นเรื่องtry {} catch(){}และข้อยกเว้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.