เป็นการปฏิบัติที่ไม่ดีที่จะกลับมาจากภายใน try catch ในที่สุดหรือไม่?


128

เช้านี้ฉันเจอโค้ดบางอย่างที่มีลักษณะดังนี้:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

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

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


13
ประโยชน์อย่างหนึ่งของรูปแบบนี้คือคุณไม่จำเป็นต้องประกาศxนอกtryบล็อก คุณสามารถเก็บประกาศไว้ใกล้เคียงกับการใช้งาน
David R Tribble

คำตอบ:


169

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


19

สุดท้ายจะถูกประหารชีวิตไม่ว่าอย่างไรก็ตามมันไม่สำคัญ


9
ไม่ในความเป็นจริงมันไม่ใช่แค่การเสียบออกเท่านั้นมีข้อยกเว้นบางอย่างที่เรียกว่า async exceptions เช่น StackOverflowException, ThreadAbortException และ OutOfMemoryException ซึ่งอาจทำให้บล็อกในที่สุดไม่ถูกเรียกใช้งาน อ่านเกี่ยวกับขอบเขตการดำเนินการที่ จำกัด สำหรับการจัดการสถานการณ์เหล่านี้
Mehrdad Afshari

ลิงค์เหล่านี้อธิบายมัน: return Statementและtry ... catch ... ในที่สุด Statement
amit jha

14

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

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

ดังนั้นฉันจะจัดเรียงรหัสเพื่อให้คำสั่งส่งคืนปรากฏหลังคำสั่งสุดท้ายเสมอ


9

สิ่งนี้อาจตอบคำถามของคุณได้

จะเกิดอะไรขึ้นในการลอง {return x; } ในที่สุด {x = null; } คำให้การ?

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

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


อืมน่าสนใจมาก นั่นหมายความว่าปลอดภัย แต่หมายความว่าควรหลีกเลี่ยงหรือไม่?
lomaxx

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

3
ฉันมักจะเห็นด้วยกับความชอบส่วนตัวของคุณ :)
lomaxx

ฉันคิดว่าผลตอบแทนที่ดีมันอยู่ที่ไหน เมธอดจะส่งคืนค่าเว้นแต่จะมีการโยนข้อยกเว้น ไม่สำคัญว่าจะมีข้อยกเว้นเกิดขึ้นในรหัสการล้างข้อมูลในที่สุดหรือไม่
Lawrence Dol

โปรดทราบว่าข้อ จำกัด ในการย้อนกลับจากในที่สุดไม่มีอยู่ใน Java (แต่ฉันคิดว่าข้อ จำกัด นั้นดี - ชื่นชม C #)
Lawrence Dol

5

ตามหน้าที่ไม่มีความแตกต่าง

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


ฉันจะท้าทายสิ่งนี้เนื่องจากคุณสามารถจบลงด้วยการซ้อนกันมากขึ้นซึ่งทำให้ยากต่อการอ่านความซับซ้อนของ
วัฏจักรที่

3

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

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

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

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