เหตุใดการจับที่ว่างเปล่าจึงปิดกั้นความคิดที่ไม่ดี [ปิด]


194

ฉันเพิ่งเห็นคำถามเกี่ยวกับลองจับซึ่งคน (รวมถึง Jon Skeet) ว่าบล็อกว่างเปล่าจับเป็นความคิดที่ไม่ดีจริง ๆ ทำไมเป็นเช่นนี้ ไม่มีสถานการณ์ที่จับเปล่าไม่มีการตัดสินใจออกแบบที่ผิดหรือเปล่า?

ตัวอย่างเช่นฉันหมายถึงบางครั้งคุณต้องการรับข้อมูลเพิ่มเติมจากที่อื่น (เว็บเซอร์, ฐานข้อมูล) และคุณไม่สนใจว่าคุณจะได้รับข้อมูลนี้หรือไม่ ดังนั้นคุณพยายามที่จะรับมันและหากมีอะไรเกิดขึ้นก็ไม่เป็นไรฉันจะเพิ่ม "catch (ข้อยกเว้นละเว้น) {}" และนั่นคือทั้งหมด


53
ฉันจะเขียนความคิดเห็นอธิบายว่าทำไมมันควรจะว่างเปล่า
Mehrdad Afshari

5
... หรืออย่างน้อยก็บันทึกว่ามันถูกจับได้
ด้านข

2
@ocdecio: หลีกเลี่ยงสำหรับโค้ดการล้างข้อมูลไม่ควรหลีกเลี่ยงโดยทั่วไป
จอห์นแซนเดอร์

1
@ocdecio: อีกกรณีหนึ่งที่จะหลีกเลี่ยงการใช้ try..catch คือเมื่อคุณตรวจพบข้อยกเว้นสำหรับความล้มเหลวประเภทที่รู้จัก เช่นข้อยกเว้นการแปลงตัวเลข
MPritchard

1
@ocdecio - ลอง .. ในที่สุดก็ดีกว่าลอง .. จับได้ผิดพลาดเพราะข้อผิดพลาดยังคงอยู่ในสแต็ค - เพื่อจัดการกรอบหรือฆ่าโปรแกรมและแสดงต่อผู้ใช้ - ผลลัพธ์ทั้งคู่ดีกว่า " ความล้มเหลวเงียบ "
เนท

คำตอบ:


298

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

มันเทียบเท่ากับการเขียนโปรแกรมการใส่เทปสีดำบนไฟเตือนเครื่องยนต์

ผมเชื่อว่าวิธีการที่คุณจัดการกับข้อยกเว้นขึ้นอยู่กับสิ่งที่ชั้นของซอฟต์แวร์ที่คุณกำลังทำงานอยู่ใน: ข้อยกเว้นในป่าฝนเขตร้อน


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

37
ชอบการเปรียบเทียบ - และชอบกฏทั้งหมดมีข้อยกเว้น ตัวอย่างเช่นคุณสามารถใช้เทปสีดำบนนาฬิกาที่กะพริบบน VCR ของคุณได้อย่างสมบูรณ์แบบหากคุณไม่ต้องการบันทึกเทปที่กำหนดเวลาไว้ (สำหรับคนชราทุกคนที่จำได้ว่าเป็น VCR)
Michael Burr

3
เช่นเดียวกับการออกเดินทางอื่น ๆ จากการปฏิบัติที่ยอมรับให้ทำตามความเหมาะสมและจัดทำเอกสารเพื่อให้คนต่อไปรู้ว่าคุณทำอะไรและทำไม
David Thornley

5
@ Jason: อย่างน้อยที่สุดคุณควรรวมความคิดเห็นโดยละเอียดเพื่ออธิบายว่าทำไมคุณถึงปิดบังข้อยกเว้น
Ned Batchelder

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

38

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

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


11

ฉันจะไม่ยืดสิ่งต่าง ๆ เท่าที่จะบอกได้ว่าใครใช้บล็อก catch ว่างเปล่าเป็นโปรแกรมเมอร์ที่ไม่ดีและไม่รู้ว่าเขากำลังทำอะไร ...

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

ตัวอย่างเช่นลองพิจารณาไลบรารี่เซิร์ฟเวอร์ http บางตัวฉันไม่สนหรอกถ้าเซิร์ฟเวอร์มีข้อยกเว้นเนื่องจากไคลเอ็นต์ได้ยกเลิกการเชื่อมต่อและindex.htmlไม่สามารถส่งได้


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

8

มีอินสแตนซ์ที่หายากซึ่งสามารถพิสูจน์ได้ ใน Python คุณมักจะเห็นสิ่งก่อสร้างประเภทนี้:

try:
    result = foo()
except ValueError:
    result = None

ดังนั้นมันอาจจะโอเค (ขึ้นอยู่กับใบสมัครของคุณ):

result = bar()
if result == None:
    try:
        result = foo()
    except ValueError:
        pass # Python pass is equivalent to { } in curly-brace languages
 # Now result == None if bar() returned None *and* foo() failed

ในโครงการ. NET ล่าสุดฉันต้องเขียนรหัสเพื่อระบุ DLLs ของปลั๊กอินเพื่อค้นหาคลาสที่ใช้อินเทอร์เฟซที่แน่นอน บิตของรหัสที่เกี่ยวข้อง (ใน VB.NET, ขอโทษ) คือ:

    For Each dllFile As String In dllFiles
        Try
            ' Try to load the DLL as a .NET Assembly
            Dim dll As Assembly = Assembly.LoadFile(dllFile)
            ' Loop through the classes in the DLL
            For Each cls As Type In dll.GetExportedTypes()
                ' Does this class implement the interface?
                If interfaceType.IsAssignableFrom(cls) Then

                    ' ... more code here ...

                End If
            Next
        Catch ex As Exception
            ' Unable to load the Assembly or enumerate types -- just ignore
        End Try
    Next

แม้ว่าในกรณีนี้ฉันยอมรับว่าการบันทึกความล้มเหลวบางแห่งอาจเป็นการปรับปรุง


ฉันอ้างถึง log4net เป็นหนึ่งในอินสแตนซ์เหล่านั้นก่อนที่ฉันจะเห็นคำตอบของคุณ
Scott Lawrence

7

บล็อกที่ว่างเปล่ามักจะใส่เพราะ coder ไม่รู้จริงๆว่ากำลังทำอะไรอยู่ ที่องค์กรของฉันบล็อก catch ว่างต้องมีข้อคิดเห็นว่าทำไมการไม่ทำอะไรเลยยกเว้นเป็นความคิดที่ดี

ในบันทึกที่เกี่ยวข้องคนส่วนใหญ่ไม่ทราบว่าสามารถลอง {} บล็อกด้วยการจับ {} หรือในที่สุด {} จำเป็นต้องมีเพียงหนึ่งรายการเท่านั้น


1
+1 ฉันจะเน้น 'หรือ' ในประโยคสุดท้ายนั้นเพื่อเพิ่มผลกระทบ
MPritchard

ย่อหน้าที่สองนั้นอาจขึ้นอยู่กับภาษาใช่มั้ย
David Z

3
เว้นแต่ของหลักสูตรที่คุณกำลังพูดถึง IE6 หรือ IE7 ;-) ... ที่จับISจำเป็นหรือในที่สุดก็ไม่ได้ดำเนินการ (สิ่งนี้ได้รับการแก้ไขใน IE8 btw)
scunliffe

แหล่งที่มา: webbugtrack.blogspot.com/2007/11/…
scunliffe

จริงแท้แน่นอน. อาจคุ้มค่าที่จะเน้นภาษา ผมเชื่อว่าจะปรับ .net
MPritchard

7

ข้อยกเว้นควรถูกโยนหากมีข้อยกเว้นอย่างแท้จริง - มีบางสิ่งที่เกิดขึ้นเกินกว่ามาตรฐาน บล็อกการจับที่ว่างเปล่าโดยทั่วไปบอกว่า "มีบางสิ่งไม่ดีเกิดขึ้น แต่ฉันไม่สนใจ" นี่เป็นความคิดที่ไม่ดี

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


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

ใช่มีเวลาและสถานที่สำหรับทุกสิ่ง โดยทั่วไปแล้วฉันคิดว่าการบล็อก catch ว่างเปล่าเป็นสิ่งที่ดีเป็นข้อยกเว้นของกฎ - เป็นกรณีที่ไม่ค่อยเกิดขึ้นซึ่งคุณต้องการละเว้นข้อยกเว้นอย่างแท้จริง (โดยทั่วไป IMO เป็นผลมาจากการใช้ข้อยกเว้นที่ไม่ดี)
Reed Copsey

2
@David Thornley: คุณจะรู้ได้อย่างไรว่ามันจะไม่ส่งผลกระทบต่อสิ่งใดหากคุณไม่ได้ตรวจสอบข้อยกเว้นในการพิจารณาว่าเป็นข้อผิดพลาดที่คาดหวังและไร้ความหมายหรือไม่
Dave Sherohman

2
@Dave: ในขณะที่catch (Exception) {}เป็นความคิดที่ไม่ดีcatch (SpecificExceptionType) {}อาจจะดีอย่างสมบูรณ์ โปรแกรมเมอร์ DID ตรวจสอบข้อยกเว้นโดยใช้ข้อมูลชนิดใน catch clause
Ben Voigt

7

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

แต่ถึงแม้ในกรณีนั้นข้อความดีบั๊กอาจอยู่ในลำดับ


6

Per Josh Bloch - รายการที่ 65: อย่าเพิกเฉยข้อยกเว้นของJava ที่มีประสิทธิภาพ :

  1. บล็อก catch ว่างเปล่าเอาชนะวัตถุประสงค์ของข้อยกเว้น
  2. อย่างน้อยที่สุดบล็อก catch ควรมีข้อคิดเห็นที่อธิบายว่าทำไมจึงสมควรละเว้นข้อยกเว้น

3

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

มันคล้ายกับของ VB6 On Error Resume Nextยกเว้นว่าสิ่งใดในบล็อกลองหลังจากโยนข้อยกเว้นจะถูกข้าม

ซึ่งไม่ได้ช่วยอะไรเลยเมื่อมีบางสิ่งเกิดขึ้น


ฉันจะพูดว่า "On Error Resume Next" แย่กว่านี้ - เพียงลองบรรทัดถัดไปโดยไม่คำนึงถึง การจับที่ว่างเปล่าจะข้ามไปเพื่อส่งผ่านการปิดคำสั่ง try
MPritchard

จุดดี. ฉันอาจจะทราบว่าในการตอบสนองของฉัน
Powerlord

1
นี้ไม่เป็นความจริงว่าถ้าคุณมีความพยายามที่ว่างเปล่า ... จับกับประเภทเฉพาะข้อยกเว้นแล้วมันจะไม่สนใจเพียงแค่ชนิดของข้อยกเว้นนี้และที่อาจจะถูกต้องตามกฎหมาย ...
Meta อัศวิน

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

@Scott: ภาษาบางภาษา (เช่น Java) ได้ตรวจสอบข้อยกเว้น ... ข้อยกเว้นที่คุณถูกบังคับให้ต้องเขียน catch catch สำหรับ
Powerlord

3

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


2

ฉันคิดว่าการบล็อก catch ว่างเปล่าอย่างสมบูรณ์เป็นความคิดที่ไม่ดีเพราะไม่มีวิธีที่จะอนุมานได้ว่าการละเว้นข้อยกเว้นนั้นเป็นพฤติกรรมตามที่ตั้งใจไว้ของโค้ด ไม่จำเป็นที่จะกลืนข้อยกเว้นและส่งคืนค่าเท็จหรือค่า Null หรือค่าอื่น ๆ ในบางกรณี เฟรมเวิร์ก. net มีวิธี "ลอง" มากมายที่ทำหน้าที่นี้ ตามกฎทั่วไปหากคุณกลืนข้อยกเว้นให้เพิ่มความคิดเห็นและคำสั่งบันทึกหากแอปพลิเคชันรองรับการบันทึก


1

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


1

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


1

ฉันพบว่าคำสั่ง catch ที่น่ารำคาญที่สุดคือเมื่อโปรแกรมเมอร์รายอื่นทำมัน สิ่งที่ฉันหมายถึงคือเมื่อคุณต้องการแก้จุดบกพร่องรหัสจากบุคคลอื่นใด ๆ คำสั่ง catch ที่ว่างเปล่าทำให้งานนั้นยากขึ้นกว่าที่คุณต้องการ IMHO catch statement ควรแสดงข้อความแสดงข้อผิดพลาดบางประเภทเสมอ - แม้ว่าข้อผิดพลาดจะไม่ได้รับการจัดการอย่างน้อยก็ควรตรวจจับได้ (alt. เปิดเฉพาะในโหมดดีบักเท่านั้น)


1

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

try
{
    // Do some processing.
}
catch (FileNotFound fnf)
{
    HandleFileNotFound(fnf);
}
catch (Exception e)
{
    if (!IsGenericButExpected(e))
        throw;
}

public bool IsGenericButExpected(Exception exception)
{
    var expected = false;
    if (exception.Message == "some expected message")
    {
        // Handle gracefully ... ie. log or something.
        expected = true;
    }

    return expected;
}

1
นั่นไม่ใช่รูปแบบมาตรฐานที่คุณแนะนำให้คนอื่นใช้ คนส่วนใหญ่เพิ่งจะจับข้อยกเว้นของสิ่งที่พวกเขาคาดหวังและไม่ใช่คนที่พวกเขาไม่ได้ ฉันสามารถดูบางสถานการณ์ที่วิธีการของคุณจะถูกต้องเพียงระมัดระวังการโพสต์ในฟอรั่มเช่นนี้ที่ผู้คนมักจะอ่านสิ่งเช่นนี้เพราะพวกเขาไม่เข้าใจในสถานที่แรก;)
MPritchard

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

ฉันเคยคิดเกี่ยวกับ COMExceptions คุณสามารถทดสอบ ErrorCode ที่เฉพาะเจาะจงและจัดการกับรหัสที่คุณคาดหวัง ฉันทำสิ่งนี้บ่อยครั้งเมื่อตั้งโปรแกรมกับ ArcOjbects
xanadont

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

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

1

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

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

ตัวอย่างอื่น: CLR 2.0 เปลี่ยนวิธีการจัดการข้อยกเว้นที่ไม่ได้จัดการในเธรด finalizer ก่อนหน้า 2.0 กระบวนการได้รับอนุญาตให้อยู่รอดในสถานการณ์นี้ ใน CLR ปัจจุบันกระบวนการจะถูกยกเลิกในกรณีที่มีข้อยกเว้นที่ไม่สามารถจัดการได้บนเธรด finalizer

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


1
ตัวอย่างเช่นฉันหมายถึงบางครั้งคุณต้องการรับข้อมูลเพิ่มเติมจากที่อื่น (เว็บเซอร์, ฐานข้อมูล) และคุณไม่สนใจว่าคุณจะได้รับข้อมูลนี้หรือไม่ ดังนั้นคุณพยายามที่จะรับมันและหากมีอะไรเกิดขึ้นก็ไม่เป็นไรฉันจะเพิ่ม "catch (ข้อยกเว้นละเว้น) {}" และนั่นคือทั้งหมด

ดังนั้นไปกับตัวอย่างของคุณมันเป็นความคิดที่ไม่ดีในกรณีนั้นเพราะคุณกำลังจับและไม่สนใจข้อยกเว้นทั้งหมด ถ้าคุณจับได้เพียงอย่างเดียวEInfoFromIrrelevantSourceNotAvailableและเพิกเฉยมันก็น่าจะดี แต่คุณก็ไม่ได้ คุณไม่สนใจENetworkIsDownซึ่งอาจจะสำคัญหรือไม่สำคัญก็ได้ คุณไม่สนใจENetworkCardHasMeltedและEFPUHasDecidedThatOnePlusOneIsSeventeenซึ่งเกือบจะสำคัญอย่างแน่นอน

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


1

มีสถานการณ์ที่คุณอาจใช้พวกเขา แต่พวกเขาควรจะไม่บ่อยนัก สถานการณ์ที่ฉันอาจใช้อย่างใดอย่างหนึ่งรวมถึง:

  • การบันทึกข้อยกเว้น; ขึ้นอยู่กับบริบทคุณอาจต้องการข้อยกเว้นที่ไม่สามารถจัดการได้หรือโพสต์ข้อความแทน

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

  • โปรแกรมที่ไม่สามารถล้มเหลวได้แต่อย่างน้อยก็ควรมีการบันทึกบางอย่าง

สำหรับแอปพลิเคชัน winforms ส่วนใหญ่ฉันพบว่าพอเพียงที่จะมีคำสั่งลองเดียวสำหรับผู้ใช้ทุกคน ฉันใช้วิธีการต่อไปนี้: (AlertBox เป็นเพียง MessageBox.Show wrapper)

  public static bool TryAction(Action pAction)
  {
     try { pAction(); return true; }
     catch (Exception exception)
     {
        LogException(exception);
        return false;
     }
  }

  public static bool TryActionQuietly(Action pAction)
  {
     try { pAction(); return true; }
     catch(Exception exception)
     {
        LogExceptionQuietly(exception);
        return false;
     }
  }

  public static void LogException(Exception pException)
  {
     try
     {
        AlertBox(pException, true);
        LogExceptionQuietly(pException);
     }
     catch { }
  }

  public static void LogExceptionQuietly(Exception pException)
  {
     try { Debug.WriteLine("Exception: {0}", pException.Message); } catch { }
  }

จากนั้นตัวจัดการเหตุการณ์ทุกคนสามารถทำสิ่งที่ชอบ:

  private void mCloseToolStripMenuItem_Click(object pSender, EventArgs pEventArgs)
  {
     EditorDefines.TryAction(Dispose);
  }

หรือ

  private void MainForm_Paint(object pSender, PaintEventArgs pEventArgs)
  {
     EditorDefines.TryActionQuietly(() => Render(pEventArgs));
  }

ในทางทฤษฎีคุณอาจมี TryActionSilently ซึ่งอาจดีกว่าสำหรับการแสดงผลการโทรเพื่อที่ข้อยกเว้นจะไม่สร้างข้อความจำนวนไม่รู้จบ


1

หากคุณไม่รู้ว่าต้องทำอย่างไรใน catch block คุณสามารถบันทึกข้อยกเว้นนี้ได้ แต่อย่าปล่อยว่างไว้

        try
        {
            string a = "125";
            int b = int.Parse(a);
        }
        catch (Exception ex)
        {
            Log.LogError(ex);
        }

ทำไมเรื่องนี้จึงถูกลดระดับลง
Vino

0

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

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