หากฟังก์ชั่นต้องทำการตรวจสอบโมฆะก่อนที่จะทำการออกแบบที่ไม่ดี


67

ดังนั้นฉันไม่รู้ว่านี่เป็นการออกแบบรหัสที่ดีหรือไม่ดีดังนั้นฉันจึงคิดว่าฉันควรถาม

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

สำหรับตัวอย่างพื้นฐานมาก:

// fields and properties
private Entity _someEntity;
public Entity SomeEntity => _someEntity;

public void AssignEntity(Entity entity){
    _someEntity = entity;
}
public void SetName(string name)
{
    if (_someEntity == null) return; //check to avoid null ref
    _someEntity.Name = name;
    label.SetText(_someEntity.Name);
}

ดังนั้นคุณจะเห็นการตรวจสอบ im สำหรับ null ทุกครั้ง แต่วิธีการนี้ควรไม่มีเช็คนี้หรือไม่?

ตัวอย่างเช่นควรโค้ดภายนอกทำความสะอาดข้อมูลก่อนมือดังนั้นวิธีการไม่จำเป็นต้องตรวจสอบเช่นด้านล่าง:

 if(entity != null) // this makes the null checks redundant in the methods
 {
     Manager.AssignEntity(entity);
     Manager.SetName("Test");
 }

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


7
จะเกิดอะไรขึ้นเมื่อมีคนไม่ทำการตรวจสอบค่าว่างและ SetName ส่งข้อยกเว้นต่อไป
Robert Harvey

5
จะเกิดอะไรขึ้นถ้าฉันอยากให้อีเว้นท์บางอย่างไร้ค่า? คุณตัดสินใจในสิ่งที่คุณต้องการบางอย่างอีเวนท์อาจเป็นค่าว่างหรือไม่สามารถทำได้จากนั้นคุณก็เขียนโค้ดของคุณตามนั้น หากคุณไม่ต้องการให้มันเป็น Null คุณสามารถแทนที่เช็คด้วย asserts ได้
gnasher729

5
คุณสามารถดูขอบเขตของ Gary Bernhardtพูดคุยเกี่ยวกับการแบ่งที่ชัดเจนระหว่างการฆ่าเชื้อข้อมูล (เช่นการตรวจสอบ nulls ฯลฯ ) ในเปลือกนอกและมีระบบแกนกลางที่ไม่ต้องสนใจสิ่งนั้น - และเพียงแค่ทำมัน งาน.
mgarciaisaia

1
ด้วย C # 8 คุณอาจไม่ต้องกังวลเกี่ยวกับข้อยกเว้นการอ้างอิงแบบ null เมื่อเปิดการตั้งค่าที่ถูกต้อง: blogs.msdn.microsoft.com/dotnet/2017/11/15/…
J --M

3
นี่คือหนึ่งในเหตุผลที่ทีมภาษา C # ต้องการแนะนำประเภทการอ้างอิงแบบ nullable (และไม่ใช่
null

คำตอบ:


168

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

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

  1. อย่ารบกวนการตรวจสอบและปล่อยให้รันไทม์โยนข้อยกเว้น nullpointer
  2. ตรวจสอบและโยนข้อยกเว้นด้วยข้อความที่ดีกว่าข้อความ NPE พื้นฐาน

วิธีที่สามทำงานได้ดีกว่า แต่มีประสิทธิภาพมากกว่า:

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

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

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


10
@aroth: การออกแบบใด ๆ ของซอฟต์แวร์รวมอยู่ด้วยจะมีข้อ จำกัด การออกแบบอย่างมากคือการเลือกว่าข้อ จำกัด เหล่านั้นจะไปที่ใดและมันก็ไม่ได้เป็นความรับผิดชอบของฉันและไม่ควรเป็นเพราะฉันยอมรับการป้อนข้อมูลใด ๆ และคาดว่าจะทำสิ่งที่มีประโยชน์กับมัน ฉันรู้ว่าnullผิดหรือไม่ถูกต้องเพราะในห้องสมุดสมมุติฉันได้กำหนดประเภทข้อมูลและฉันได้กำหนดสิ่งที่ถูกต้องและสิ่งที่ไม่ คุณเรียกว่า "บังคับสมมติฐาน" แต่เดาว่า: นั่นคือสิ่งที่ห้องสมุดซอฟต์แวร์ทุกแห่งมีอยู่จริง มีบางครั้งที่ null เป็นค่าที่ถูกต้อง แต่นั่นไม่ใช่ "เสมอ"
whatsisname

4
" รหัสของคุณเสียเพราะไม่สามารถจัดการnullได้อย่างถูกต้อง" - นี่เป็นความเข้าใจที่ผิดว่าการจัดการที่เหมาะสมหมายถึงอะไร สำหรับการเขียนโปรแกรม Java ส่วนใหญ่ก็หมายถึงการขว้างปายกเว้นสำหรับการใด ๆการป้อนข้อมูลที่ไม่ถูกต้อง ใช้@ParametersAreNonnullByDefaultมันหมายความว่ายังสำหรับทุกเว้นแต่อาร์กิวเมนต์ที่ถูกทำเครื่องหมายเป็นnull @Nullableการทำสิ่งอื่นหมายถึงการทำให้เส้นทางยาวขึ้นจนในที่สุดมันก็พัดไปที่อื่นและทำให้เวลาที่ใช้ในการดีบั๊กนั้นยาวนานขึ้น โดยการเพิกเฉยปัญหาคุณอาจบรรลุได้ว่ามันไม่เคยโบยบิน แต่พฤติกรรมที่ไม่ถูกต้องนั้นรับประกันได้เลยทีเดียว
maaartinus

4
@aroth Dear Lord ฉันจะเกลียดการทำงานกับรหัสที่คุณเขียน การระเบิดนั้นดีกว่าการทำอะไรที่ไร้สาระซึ่งเป็นอีกทางเลือกเดียวสำหรับการป้อนข้อมูลที่ไม่ถูกต้อง ข้อยกเว้นบังคับให้ฉันผู้โทรตัดสินใจว่าสิ่งที่ถูกต้องคืออะไรในกรณีเหล่านั้นเมื่อวิธีการนั้นไม่สามารถคาดเดาสิ่งที่ฉันตั้งใจได้ การตรวจสอบข้อยกเว้นและการขยายที่ไม่จำเป็นExceptionนั้นเป็นการโต้วาทีที่ไม่เกี่ยวข้องอย่างสมบูรณ์ (ฉันเห็นด้วยว่าทั้งคู่มีปัญหา) สำหรับตัวอย่างนี้nullชัดเจนว่าไม่มีเหตุผลที่นี่ถ้าจุดประสงค์ของชั้นเรียนคือการเรียกใช้เมธอดบนวัตถุ
jpmc26

3
"รหัสของคุณไม่ควรบังคับให้มีการสันนิษฐานออกไปสู่โลกของผู้โทร" - เป็นไปไม่ได้ที่จะไม่บังคับให้ผู้เรียกเข้ามาตั้งสมมติฐาน นั่นเป็นเหตุผลที่เราต้องทำให้สมมติฐานเหล่านี้ชัดเจนที่สุด
Diogo Kollross

3
@aroth รหัสของคุณเสียเพราะมันผ่านรหัสของฉันเป็นโมฆะเมื่อมันควรจะผ่านสิ่งที่มีชื่อเป็นคุณสมบัติ พฤติกรรมใด ๆ ที่นอกเหนือจากการระเบิดนั้นเป็นประเภท IMHO แบบแบ็คดอร์ที่แปลกประหลาดในโลกแห่งความลับ
mbrig

56

เนื่องจาก_someEntityสามารถแก้ไขได้ทุกขั้นตอนดังนั้นจึงเหมาะสมที่จะทดสอบทุกครั้งที่SetNameมีการเรียก ท้ายที่สุดมันอาจมีการเปลี่ยนแปลงตั้งแต่ครั้งสุดท้ายที่วิธีการที่เรียกว่า แต่ทราบว่ารหัสในSetNameไม่ด้ายปลอดภัยเพื่อให้คุณสามารถดำเนินการตรวจสอบว่าในหนึ่งด้ายได้_someEntityตั้งค่าให้nullอีกแล้วรหัสจะ barf NullReferenceExceptionอยู่แล้ว

วิธีหนึ่งในการแก้ไขปัญหานี้คือการป้องกันให้ดียิ่งขึ้นและทำสิ่งใดสิ่งหนึ่งต่อไปนี้:

  1. ทำสำเนาของท้องถิ่น_someEntityและการอ้างอิงที่คัดลอกผ่านวิธีการ
  2. ใช้ตัวล็อก_someEntityเพื่อให้แน่ใจว่ามันจะไม่เปลี่ยนแปลงเมื่อวิธีการทำงาน
  3. ใช้ a try/catchและทำการกระทำแบบเดียวกันกับสิ่งNullReferenceExceptionที่เกิดขึ้นภายในวิธีการที่คุณดำเนินการในการตรวจสอบโมฆะครั้งแรก (ในกรณีนี้คือการnopกระทำ)

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

private readonly Entity _someEntity;

public Constructor(Entity someEntity)
{
    if (someEntity == null) throw new ArgumentNullException(nameof(someEntity));
    _someEntity = someEntity;
}

public void SetName(string name)
{
    _someEntity.Name = name;
    label.SetText(_someEntity.Name);
}

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

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

private Entity _someEntity;
public Entity SomeEntity => _someEntity;

public void AssignEntity(Entity entity){
    _someEntity = entity;
}

สามารถถูกแทนที่ด้วย:

public Entity SomeEntity { get; set; }

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


5
ทำไมถึงตอบคำถามนี้ คำถามที่อยู่การตรวจสอบเป็นโมฆะและนี่คือการตรวจสอบรหัสสวย
IEatBagels

17
@TopinFrassi มันอธิบายว่าวิธีการตรวจสอบโมฆะปัจจุบันไม่ปลอดภัยเธรด จากนั้นจะสัมผัสกับเทคนิคการเขียนโปรแกรมป้องกันอื่น ๆ เพื่อหลีกเลี่ยงปัญหานั้น จากนั้นจะสรุปคำแนะนำในการใช้ความไม่สามารถเปลี่ยนแปลงได้เพื่อหลีกเลี่ยงความจำเป็นที่จะต้องตั้งโปรแกรมป้องกันไว้ตั้งแต่แรก และเป็นโบนัสเพิ่มเติมมันให้คำแนะนำเกี่ยวกับวิธีการจัดโครงสร้างโค้ดให้ดีขึ้นเช่นกัน
David Arno

23

แต่วิธีการนี้ควรไม่มีเช็คนี้หรือไม่?

นี่คือทางเลือกของคุณ

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

สัญญาประเภทใดที่คุณต้องการออกแบบขึ้นอยู่กับคุณ สิ่งที่สำคัญคือ

  • สร้าง API ที่มีประโยชน์และสอดคล้องและ

  • จัดทำเอกสารได้ดีโดยเฉพาะอย่างยิ่งสำหรับกรณีขอบเหล่านั้น

มีกรณีใดบ้างที่วิธีการของคุณถูกเรียก?


ความปลอดภัยของเธรดคือข้อยกเว้นไม่ใช่กฎเมื่อมีการเข้าถึงพร้อมกัน ดังนั้นจึงมีการบันทึกสถานะการใช้งาน / สถานะโกลบอลที่ซ่อนอยู่รวมถึงกรณีใด ๆ
Deduplicator

14

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

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

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

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

ตัวอย่างเช่นคุณไม่ต้องการที่จะอยู่ในสถานการณ์นี้:

class Person { ... }
...
class ExpenseReport { 
  public void SubmitReport(Person approver) { 
    if (approver == null) ... do something ...

และที่ไซต์การโทร:

// I guess this works but I don't know what it means
expenses.SubmitReport(null); 

เนื่องจาก (1) คุณกำลังฝึกผู้โทรว่าโมฆะเป็นค่าที่ดีและ (2) ไม่ชัดเจนว่าความหมายของค่านั้นคืออะไร ค่อนข้างทำสิ่งนี้:

class ExpenseReport { 
  public static readonly Person ApproverNotRequired = new Person();
  public static readonly Person ApproverUnknown = new Person();
  ...
  public void SubmitReport(Person approver) { 
    if (approver == null) throw ...
    if (approver == ApproverNotRequired) ... do something ...
    if (approver == ApproverUnknown) ... do something ...

และตอนนี้ไซต์การโทรมีลักษณะดังนี้:

expenses.SubmitReport(ExpenseReport.ApproverNotRequired);

และตอนนี้ผู้อ่านรหัสรู้ถึงความหมายของมัน


ยังดีกว่าไม่มีสายโซ่ของifวัตถุว่างเปล่า แต่ใช้ polymorphism เพื่อให้มันทำงานอย่างถูกต้อง
Konrad Rudolph

@ KonradRudolph: แน่นอนว่ามันเป็นเทคนิคที่ดี ฉันชอบที่จะใช้สำหรับโครงสร้างข้อมูลที่ฉันทำEmptyQueueประเภทที่พ่นเมื่อ dequeued และอื่น ๆ
Eric Lippert

@EricLippert - ยกโทษให้ฉันเพราะฉันยังเรียนอยู่ที่นี่ แต่ถ้าPersonคลาสนั้นไม่เปลี่ยนรูปและมันไม่มีตัวสร้างอาร์กิวเมนต์เป็นศูนย์คุณจะสร้างApproverNotRequiredหรือApproverUnknownอินสแตนซ์ของคุณ อย่างไร กล่าวอีกนัยหนึ่งคุณจะผ่านค่าตัวสร้างอะไร

2
ฉันชอบที่จะตอบคำถาม / ความคิดเห็นของคุณใน SE พวกเขามีความรู้ลึกซึ้งเสมอ ทันทีที่ฉันเห็นการใช้วิธีการภายใน / ส่วนตัวฉันเลื่อนลงโดยคาดหวังว่ามันจะเป็นคำตอบของ Eric Lippert ก็ไม่ผิดหวัง :)
bob esponja

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

8

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

public static class Foo {
    public static void Frob(Bar a, Bar b) {
        if (a == null) throw new ArgumentNullException(nameof(a));
        if (b == null) throw new ArgumentNullException(nameof(b));

        a.Something = b.Something;
    }
}

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

a.Something = b.Something;

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

ฉันจะทราบว่ารูปแบบในรหัสต้นฉบับของคุณ:

if (x == null) return;

สามารถใช้งานได้ในบางสถานการณ์มันยังสามารถ (อาจบ่อยกว่า) ให้วิธีที่ดีในการปิดบังปัญหาพื้นฐานในโค้ดเบสของคุณ


4

ไม่มีเลย แต่ขึ้นอยู่กับ

คุณทำการตรวจสอบการอ้างอิงเป็นโมฆะถ้าคุณต้องการที่จะตอบสนอง

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

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


4

ส่วนขยายบางส่วนของคำตอบของ @ null แต่จากประสบการณ์ของฉันแล้ว null จะตรวจสอบไม่ว่าจะเกิดอะไรขึ้น

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

ทีนี้วิธีที่คุณจะจัดการกับnullคุณค่านั้นขึ้นอยู่กับกรณีการใช้งานของคุณเป็นอย่างมาก

หากnullเป็นค่าที่ยอมรับได้เช่นพารามิเตอร์ตัวใดตัวที่สองถึงห้าถึงรูทีน MSVC _splitpath () แสดงว่าการจัดการอย่างเงียบ ๆ นั้นเป็นพฤติกรรมที่ถูกต้อง

หากnullไม่ควรเกิดขึ้นเมื่อเรียกรูทีนที่มีปัญหาเช่นในกรณีของ OP สัญญา API ต้องAssignEntity()ได้รับการเรียกด้วยการใช้งานที่ถูกต้องEntityจากนั้นโยนข้อยกเว้นหรือไม่เช่นนั้นจะทำให้แน่ใจว่าคุณทำเสียงดังมากในกระบวนการ

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


หรือหลีกเลี่ยงมันทั้งหมด (48 นาที 29 วินาที: "ไม่เคยใช้หรืออนุญาตให้มีตัวชี้ Null ใด ๆ ที่อยู่ใกล้กับโปรแกรมของคุณ" )
Peter Mortensen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.