這聽起來像是你在類似Groovy的無效解引用操作符之後,它會讓你編寫if (School?.ClassRoom?.Pupil?.Age != null)
--但是C#沒有這樣的東西。
恐怕你有檢查每個屬性爲無效,假設它可以是空:
if (School != null && School.ClassRoom != null && School.ClassRoom.Pupil != null
&& School.ClassRoom.Pupil.Age != null)
{
MyMethod(School.ClassRoom.Pupil.Age);
}
當然,你可以把這個整個if
塊包括方法調用本身一個輔助方法,然後調用它。
這就是假設它對每個屬性有效,以爲 null開頭。如果你能夠設計你的類,那麼甚至不允許使用空值 - 並且你在contsructors等中驗證了這一點 - 你的代碼很可能會變得更加乾淨。
值得注意的是,這裏有兩種替代方法 - 克里斯在另一個答案中提出的方法是爲每個屬性創建一個「默認」對象;我通常發現總是需要在構造函數中提供「真實」值更好。沒有真實數據的默認對象最終會導致比NullReferenceException
問題難以跟蹤的錯誤,因爲您可以長時間快樂地處理「虛擬」數據,並在最後得到錯誤的結果。當然,有些時候是是正確的選擇,但是 - 尤其是當涉及到收藏時。這取決於實際情況。
編輯:賽義德建議在評論中的擴展方法。我想這會是這樣的:(適當調整類型)
public static int? PupilAgeOrNull(this School school)
{
return school != null &&
school.ClassRoom != null &&
school.ClassRoom.Pupil != null
? school.ClassRoom.Pupil.Age : null;
}
我肯定更喜歡嘗試讓一切非空別處的想法,但如果你需要它,這將做到這一點。雖然我感覺不對。這種直覺的核心是你正在導航三個或四個屬性 - 這對我來說就像是違反了Law of Demeter。現在我不是那種對這種事情有教條意義的人,但是在School
上加上擴展方法對我來說太過於具體,對於如此長的屬性路徑。
另一種選擇 - 這也是有些討厭,IMO - 是寫三個不同的推廣方法:
public static ClassRoom ClassRoomOrNull(this School school)
{
return school == null ? null : school.ClassRoom;
}
public static Pupil PupilOrNull(this ClassRoom classRoom)
{
return classRoom == null ? null : classRoom.Pupil;
}
public static int? AgeOrNull(this Pupil pupil)
{
return pupil == null ? null : pupil.Age;
}
然後,你可以寫:
int? age = School.ClassRoomOrNull().PupilOrNull().AgeOrNull();
if (age != null)
{
MyMethod(age);
}
這意味着,在School
擴展方法並不是那麼具體。你仍然有一長串的方法調用,我仍然試圖重新設計,以儘可能避免這種情況,但至少從School
到School.ClassRoom.Pupil.Age
沒有那麼緊密的關係。
你如何填寫School.ClassRoom數據?填充時,不允許NULL行可能是一個解決方案? – 2010-11-21 08:47:39
順便說一句,你的標題似乎並不合適。沒有任何混淆你所得到的例外。 – 2010-11-21 09:13:48
如果可能的話,我希望能夠繼續使用空類,因爲這是一個相當複雜的數據結構的一部分,如果我開始有所有的空值的新實例,那麼我認爲內存使用率將通過屋頂。 – Caustix 2010-11-21 09:55:20