อะไรคือความแตกต่างระหว่าง Raise“ foo” และ `Raise Exception.new (“ foo”)`?


คำตอบ:


121

เทคนิคแรกยก Runtimeerror กับชุดข้อความไปยังและที่สองทำให้เกิดข้อยกเว้นกับชุดข้อความไปยัง"foo""foo"

ในทางปฏิบัติมีความแตกต่างอย่างมีนัยสำคัญระหว่างเวลาที่คุณต้องการใช้อดีตและเมื่อคุณต้องการใช้แบบหลัง

พูดง่ายๆก็คือคุณอาจRuntimeErrorไม่ต้องการไฟล์Exception. บล็อกช่วยเหลือที่ไม่มีข้อโต้แย้งจะจับRuntimeErrorsได้ แต่จะไม่จับExceptions ดังนั้นหากคุณเพิ่มExceptionรหัสของคุณรหัสนี้จะไม่จับมัน:

begin
rescue
end

ในการจับExceptionคุณจะต้องทำสิ่งนี้:

begin
rescue Exception
end

ซึ่งหมายความว่าในแง่หนึ่งExceptionข้อผิดพลาด "แย่กว่า" มากกว่า a RuntimeErrorเนื่องจากคุณต้องทำงานมากขึ้นเพื่อกู้คืนจากข้อผิดพลาดนั้น

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

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

สุดท้ายฉันควรจะบอกว่าRuntimeErrorเป็นคลาสย่อยของStandardErrorคลาสและกฎที่แท้จริงก็คือแม้ว่าคุณจะสามารถอ็อบเจ็กต์ประเภทraise ใดก็ได้rescueแต่ค่าเริ่มต้นจะจับเฉพาะสิ่งที่สืบทอดมาStandardErrorเท่านั้น อย่างอื่นต้องมีความเฉพาะเจาะจง


2
ข้อมูลมากขอบคุณ บางสิ่ง: [1] ย่อหน้าสุดท้ายนั้นมีความสว่างมากที่สุดและขอให้ฉันค้นพบสิ่งที่คุณไม่ได้กล่าวถึงที่ irb: RuntimeError < StandardError < Exception[2] ดังนั้นโค้ดบล็อกที่สองจะจับทั้ง Exception และ RuntimeError [3] มันน่าสนใจ / แปลกที่การเพิ่มและช่วยเหลือแบบ "เปล่า" เกิดขึ้นเพื่อทำงานกับข้อยกเว้นนั้น ๆ [4] บางทีหลักการง่ายๆคือการเพิ่ม RuntimeError ให้กับรหัสไคลเอ็นต์ แต่เพิ่มและช่วยเหลือข้อยกเว้นที่กำหนดเองภายในรหัสของตัวเอง?
John Bachir

1
[1, 2] ใช่ [3] ไม่แน่ใจว่า ... [4] StandardErrorเมื่อฉันเขียนโปรแกรมที่มืออาชีพมากที่สุดของฉันฉันมีแนวโน้มที่จะสร้างข้อผิดพลาดประเภทที่กำหนดเองที่สืบทอดมาจาก ไม่จำเป็นต้องซับซ้อนกว่าสองสามบรรทัดเช่นclass MissingArgumentsError < StandardError; end.
Daniel Lucraft

ให้ข้อมูลมาก แต่ภายใต้สถานการณ์แบบใดที่คุณจะต้องการทิ้งข้อยกเว้นแทนที่จะเป็นข้อผิดพลาดเวลาทำงานหากข้อผิดพลาดของเวลาทำงานเป็นที่ต้องการสำหรับการเขียน libraray?
Chihung Yu

35

จากเอกสารทางการ:

raise   
raise( string )
raise( exception [, string [, array ] ] )

หากไม่มีข้อโต้แย้งจะทำให้เกิดข้อยกเว้น$!หรือเพิ่มRuntimeErrorif $!เป็นศูนย์ ด้วยStringอาร์กิวเมนต์เดียวจะเพิ่มRuntimeErrorสตริงเป็นข้อความ มิฉะนั้นพารามิเตอร์แรกควรเป็นชื่อของExceptionคลาส (หรืออ็อบเจ็กต์ที่ส่งคืนExceptionข้อยกเว้นเมื่อส่ง) พารามิเตอร์ที่สองซึ่งเป็นทางเลือกจะตั้งค่าข้อความที่เกี่ยวข้องกับข้อยกเว้นและพารามิเตอร์ที่สามคืออาร์เรย์ของข้อมูลการเรียกกลับ ข้อยกเว้นถูกจับโดยประโยคช่วยเหลือของbegin...endบล็อก

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