แนวทางปฏิบัติที่ดีที่สุด: ทิ้งข้อยกเว้นจากคุณสมบัติ


111

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


ดูเพิ่มเติมที่: stackoverflow.com/questions/633944/…
Jon B

ที่เกี่ยวข้องด้วย: stackoverflow.com/questions/1488322/…
Brian Rasmussen

1
ฉันอ่านทั้งสองคำถามแล้ว แต่ก็ไม่ได้ตอบคำถามนี้อย่างสมบูรณ์ IMO
Jon Seigel

เมื่อใดก็ตามที่จำเป็น ทั้งคำถามและคำตอบก่อนหน้านี้แสดงให้เห็นว่าได้รับอนุญาตและยินดีที่จะยกข้อยกเว้นจาก getter หรือ setter ดังนั้นคุณสามารถ "ฉลาด" ได้ง่ายๆ
Lex Li

คำตอบ:


135

Microsoft มีคำแนะนำเกี่ยวกับวิธีการออกแบบคุณสมบัติที่http://msdn.microsoft.com/en-us/library/ms229006.aspx

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

สำหรับตัวทำดัชนี Microsoft ระบุว่าเป็นที่ยอมรับสำหรับทั้ง getters และ setters ในการโยนข้อยกเว้น และอันที่จริงดัชนีหลายตัวในไลบรารี. NET ก็ทำเช่นนี้ ArgumentOutOfRangeExceptionส่วนใหญ่เป็นข้อยกเว้นที่พบบ่อย

มีเหตุผลที่ดีบางประการที่คุณไม่ต้องการทิ้งข้อยกเว้นในการรับทรัพย์สิน:

  • เนื่องจากคุณสมบัติ "ปรากฏ" เป็นเขตข้อมูลจึงไม่ชัดเจนเสมอไปว่าพวกเขาสามารถทิ้งข้อยกเว้น (ตามการออกแบบ) ได้ ในขณะที่วิธีการโปรแกรมเมอร์ได้รับการฝึกฝนให้คาดหวังและตรวจสอบว่าข้อยกเว้นเป็นผลที่คาดว่าจะได้รับจากการเรียกใช้วิธีการหรือไม่
  • Getters ถูกใช้โดยโครงสร้างพื้นฐาน. NET จำนวนมากเช่น serializers และ databinding (ใน WinForms และ WPF เป็นต้น) การจัดการกับข้อยกเว้นในบริบทดังกล่าวอาจกลายเป็นปัญหาได้อย่างรวดเร็ว
  • ผู้ตรวจแก้ปัญหาจะประเมินคุณสมบัติโดยอัตโนมัติเมื่อคุณดูหรือตรวจสอบวัตถุ ข้อยกเว้นที่นี่อาจสร้างความสับสนและชะลอความพยายามในการแก้ไขข้อบกพร่องของคุณ นอกจากนี้ยังไม่พึงปรารถนาที่จะดำเนินการอื่น ๆ ที่มีราคาแพงในคุณสมบัติ (เช่นการเข้าถึงฐานข้อมูล) ด้วยเหตุผลเดียวกัน
  • คุณสมบัติมักใช้ในรูปแบบการผูกมัด: obj.PropA.AnotherProp.YetAnother- ด้วยไวยากรณ์ประเภทนี้จะกลายเป็นปัญหาในการตัดสินใจว่าจะใส่คำสั่งการจับข้อยกเว้นที่ใด

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


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

1
ฉันไม่แน่ใจว่าฉันเข้าใจข้อโต้แย้งในคำตอบนี้ สำหรับ xample เกี่ยวกับ databinding - ทั้ง WinForms และ WPF ถูกเขียนขึ้นโดยเฉพาะเพื่อจัดการข้อยกเว้นที่ถูกโยนโดยคุณสมบัติและถือว่าเป็นความล้มเหลวในการตรวจสอบความถูกต้องซึ่งเป็นวิธีที่ดีอย่างสมบูรณ์ (บางคนเชื่อว่าเป็นวิธีที่ดีที่สุด) ในการตรวจสอบความถูกต้องของโมเดลโดเมน .
Pavel Minaev

6
@Pavel - ในขณะที่ทั้ง WinForms และ WPF สามารถกู้คืนจากข้อยกเว้นในตัวเข้าถึงคุณสมบัติได้อย่างสง่างาม แต่ก็ไม่ใช่เรื่องง่ายที่จะระบุและกู้คืนจากข้อผิดพลาดดังกล่าว ในบางกรณี (เช่นเมื่ออยู่ใน WPF ตัวตั้งค่าเทมเพลตควบคุมจะแสดงข้อยกเว้น) ข้อยกเว้นจะถูกกลืนโดยไม่โต้ตอบ ซึ่งอาจนำไปสู่เซสชันการแก้ไขจุดบกพร่องที่เจ็บปวดหากคุณไม่เคยเจอกรณีเช่นนี้มาก่อน
LBushkin

1
@Steven: แล้วคลาสนั้นจะใช้กับคุณได้มากแค่ไหนในกรณีพิเศษ? หากคุณต้องเขียนรหัสป้องกันเพื่อจัดการข้อยกเว้นเหล่านั้นทั้งหมดเนื่องจากความล้มเหลวเพียงครั้งเดียวและน่าจะจัดหาค่าเริ่มต้นที่เหมาะสมทำไมไม่ระบุค่าเริ่มต้นเหล่านั้นในการจับของคุณ หรือหากมีการโยนข้อยกเว้นคุณสมบัติให้กับผู้ใช้ทำไมไม่เพียงแค่โยน "InvalidArgumentException" ดั้งเดิมหรือที่คล้ายกันเพื่อให้พวกเขาสามารถจัดหาไฟล์การตั้งค่าที่หายไปได้
Zhaph - Ben Duguid

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

34

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

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

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


4
ขอบคุณ Pavel คำตอบนี้อยู่ใน 'ทำไม' แทนที่จะระบุเพียงว่าอีกครั้งไม่ควรทิ้งข้อยกเว้นจากคุณสมบัติ
SolutionYogi

1
ฉันไม่ชอบความคิดที่ว่าสมาชิกทุกคนIDisposableควรถูกทำให้ไร้ประโยชน์หลังจาก a Dispose. หากเรียกใช้สมาชิกจะต้องใช้ทรัพยากรที่Disposeไม่สามารถใช้งานได้ (เช่นสมาชิกจะอ่านข้อมูลจากสตรีมที่ถูกปิด) สมาชิกควรโยนObjectDisposedExceptionมากกว่าการรั่วไหลเช่นArgumentExceptionแต่หากมีรูปแบบที่มีคุณสมบัติที่แสดงถึง ค่าในบางช่องดูเหมือนว่าจะมีประโยชน์มากกว่าที่จะอนุญาตให้อ่านคุณสมบัติดังกล่าวหลังการกำจัด (ให้ค่าที่พิมพ์ครั้งสุดท้าย) มากกว่าที่จะต้องการ ...
supercat

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

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

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

24

แทบจะไม่เคยเหมาะสมกับผู้เริ่มต้นและบางครั้งก็เหมาะสมกับผู้ตั้งรับ

แหล่งข้อมูลที่ดีที่สุดสำหรับคำถามประเภทนี้คือ "Framework Design Guidelines" โดย Cwalina และ Abrams มีให้บริการในรูปแบบหนังสือผูกมัดและส่วนใหญ่ยังมีให้บริการทางออนไลน์

จากหัวข้อ 5.2: การออกแบบอสังหาริมทรัพย์

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

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


2
แม้ว่า (โดยทั่วไป) ฉันเห็นด้วยกับแนวทางดังกล่าว แต่ก็คิดว่าการให้ข้อมูลเชิงลึกเพิ่มเติมว่าเหตุใดจึงควรปฏิบัติตาม - และผลที่ตามมาจะเกิดขึ้นเมื่อถูกเพิกเฉย
LBushkin

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

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

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

2

แนวทางที่ดีวิธีหนึ่งสำหรับข้อยกเว้นคือการใช้เพื่อจัดทำโค้ดสำหรับตัวคุณเองและนักพัฒนารายอื่น ๆ ดังนี้:

ข้อยกเว้นควรมีไว้สำหรับสถานะโปรแกรมพิเศษ ซึ่งหมายความว่าคุณสามารถเขียนได้ทุกที่ที่คุณต้องการ!

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

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

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

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


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

1

ทั้งหมดนี้บันทึกไว้ใน MSDN (ตามที่เชื่อมโยงกับคำตอบอื่น ๆ ) แต่นี่เป็นกฎทั่วไป ...

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

สำหรับ getters อาจเป็นไปได้ว่าเมื่อค่าเป็นโมฆะ แต่ส่วนใหญ่เป็นสิ่งที่คุณต้องการจัดการกับรหัสการโทร (ตามแนวทางการออกแบบ)



0

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

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

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

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


0

ฉันมีรหัสนี้ซึ่งฉันไม่แน่ใจว่าจะโยนข้อยกเว้นใด

public Person
{
    public string Name { get; set; }
    public boolean HasPets { get; set; }
}

public void Foo(Person person)
{
    if (person.Name == null) {
        throw new Exception("Name of person is null.");
        // I was unsure of which exception to throw here.
    }

    Console.WriteLine("Name is: " + person.Name);
}

ฉันป้องกันไม่ให้โมเดลมีคุณสมบัติเป็นโมฆะตั้งแต่แรกโดยบังคับให้เป็นอาร์กิวเมนต์ในตัวสร้าง

public Person
{
    public Person(string name)
    {
        if (name == null) {
            throw new ArgumentNullException(nameof(name));
        }
        Name = name;
    }

    public string Name { get; private set; }
    public boolean HasPets { get; set; }
}

public void Foo(Person person)
{
    Console.WriteLine("Name is: " + person.Name);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.