อัปเดต:ตั้งแต่ Visual Studio 2015 คอมไพลเลอร์ C # (ภาษาเวอร์ชัน 6) ตอนนี้รู้จักตัว?.
ดำเนินการซึ่งทำให้ "การตรวจสอบค่า null เชิงลึก" เป็นเรื่องง่าย ดูรายละเอียดคำตอบนี้
นอกเหนือจากการออกแบบโค้ดของคุณใหม่เช่นเดียว
กับคำตอบที่ถูกลบนี้แนะนำตัวเลือกอื่น (แม้ว่าจะแย่มาก) คือการใช้try…catch
บล็อกเพื่อดูว่ามีอะไรNullReferenceException
เกิดขึ้นบ้างในระหว่างการค้นหาคุณสมบัติเชิงลึกนั้นหรือไม่
try
{
var x = cake.frosting.berries.loader;
...
}
catch (NullReferenceException ex)
{
// either one of cake, frosting, or berries was null
...
}
โดยส่วนตัวแล้วฉันจะไม่ทำสิ่งนี้ด้วยเหตุผลต่อไปนี้:
- มันดูไม่ดี
- ใช้การจัดการข้อยกเว้นซึ่งควรกำหนดเป้าหมายสถานการณ์พิเศษไม่ใช่สิ่งที่คุณคาดว่าจะเกิดขึ้นบ่อยครั้งในระหว่างการดำเนินการปกติ
NullReferenceException
s ไม่ควรถูกจับอย่างชัดเจน (ดูคำถามนี้)
ดังนั้นจึงเป็นไปได้โดยใช้วิธีการขยายบางอย่างหรือจะเป็นคุณลักษณะของภาษา [... ]
เกือบจะแน่นอนว่าจะต้องเป็นคุณลักษณะของภาษา (ซึ่งมีอยู่ใน C # 6 ในรูปแบบของ.?
และ?[]
ตัวดำเนินการ) เว้นแต่ C # จะมีการประเมินแบบขี้เกียจที่ซับซ้อนกว่านี้อยู่แล้วหรือเว้นแต่คุณต้องการใช้การสะท้อน (ซึ่งอาจไม่ใช่ ความคิดที่ดีด้วยเหตุผลด้านประสิทธิภาพและประเภทความปลอดภัย)
เนื่องจากไม่มีวิธีเพียงแค่ส่งผ่านcake.frosting.berries.loader
ไปยังฟังก์ชัน (จะได้รับการประเมินและโยนข้อยกเว้นการอ้างอิงว่าง) คุณจะต้องใช้วิธีการค้นหาทั่วไปด้วยวิธีต่อไปนี้: ใช้ในวัตถุและชื่อของคุณสมบัติในการ ค้นหา:
static object LookupProperty( object startingPoint, params string[] lookupChain )
{
// 1. if 'startingPoint' is null, return null, or throw an exception.
// 2. recursively look up one property/field after the other from 'lookupChain',
// using reflection.
// 3. if one lookup is not possible, return null, or throw an exception.
// 3. return the last property/field's value.
}
...
var x = LookupProperty( cake, "frosting", "berries", "loader" );
(หมายเหตุ: แก้ไขโค้ดแล้ว)
คุณเห็นปัญหาหลายอย่างอย่างรวดเร็วด้วยแนวทางดังกล่าว อันดับแรกคุณจะไม่ได้รับความปลอดภัยใด ๆ และอาจเป็นไปได้ในการชกมวยมูลค่าทรัพย์สินประเภทง่ายๆ ประการที่สองคุณสามารถย้อนกลับได้null
หากมีสิ่งผิดปกติเกิดขึ้นและคุณจะต้องตรวจสอบสิ่งนี้ในฟังก์ชันการโทรของคุณหรือคุณโยนข้อยกเว้นและคุณกลับไปที่จุดเริ่มต้น สามมันอาจจะช้า ประการที่สี่มันดูน่าเกลียดกว่าสิ่งที่คุณเริ่มต้นด้วยซ้ำ
[... ] หรือมันเป็นเพียงความคิดที่ไม่ดี?
ฉันจะอยู่กับ:
if (cake != null && cake.frosting != null && ...) ...
หรือไปกับคำตอบข้างต้นโดย Mehrdad Afshari
PS:ย้อนกลับไปตอนที่ฉันเขียนคำตอบนี้เห็นได้ชัดว่าฉันไม่ได้พิจารณาต้นไม้นิพจน์สำหรับฟังก์ชันแลมด้า ดูเช่นคำตอบของ @driis สำหรับวิธีแก้ปัญหาในทิศทางนี้ นอกจากนี้ยังขึ้นอยู่กับประเภทของการสะท้อนกลับดังนั้นจึงอาจทำงานได้ไม่ดีเท่ากับวิธีแก้ปัญหาที่ง่ายกว่า ( if (… != null & … != null) …
) แต่อาจตัดสินได้ดีกว่าจากมุมมองของไวยากรณ์