這幾日剛好在 Stack overflow 看到了一篇文章。邏輯很簡單,概念卻很有意思,所以決定做個註記。
(原文列於參考資料)
假設情境
已有一個客戶類別,包含「名稱」屬性。
public class Customer
{
public string Name { get; set; }
}
要取客戶的名稱,寫法很簡單就如下 :
var name = customer.Name;
然而當customer為null時,程式就會報錯。此時可以「三元條件運算子」修改如下 :
var name = customer == null ? null : customer.Name;
Null-conditional operators
在 C# 6.0 推出新的運算子 ?. 。在 docs 的說明為
- 若 a 為 null ,則 a?.x 的結果為 null。
- 若 a 為非 null ,則a?.x的結果同a.x。
此時,上述範例可改寫如下 :
var name = customer?.Name;
變得精簡許多,並與原本三元條件運算子的寫法,會得到一樣的結果。
那假如是DateTime?.Value呢
DateTime? datetime = null; // Maybe from database
var time = datetime.Value;
Nullable 的 DateTime,若在執行階段取Value時遇到null,會發生錯誤 : 「System.InvalidOperationException: 可為 Null 的物件必須具有值。」。
也許有人會很直覺的想到 : 「那就加上Null-conditional operators吧!」,如此會收到編輯階段錯誤 : 「'DateTime'未包含'Value'的定義,也找不到可接受類型'DateTime'第一個引數的可存取擴充方法'Value'」。
其原因在於Null-conditional operators的規則 : e?.x => ((e == null) ? null : e0.x),e0等同於e。若 e 為 Nullable 型別,則此狀況下 e0 為 e.Value。依此規則代換,原本的寫法意即
var time = datetime.Value.Value;
因此會出現編輯階段錯誤。到這裡或許有人已經想到 : DateTime?.Value 這樣的寫法,其實就等同 DateTime? 本身。
改用Default Value呢
某些情況下,假如無法使用 null 也可以考慮以 Default Value 作為替代,只是自身不是很喜歡這個做法。以DateTime來說,Default Value為「0001/1/1 上午 12:00:00」 、 int的Default Value為「0」 , 甚至 string 的 Default Value 是「null」! 在閱讀上較不直觀。
DateTime? datetime = null;
var timeDefaule = datetime.GetValueOrDefault();
var defaultTime = datetime ?? default(DateTime);
結語
依照每個系統的狀況與需求,資料型別的設定與邏輯都會有不同的變化。
看到文章一時間引發了好奇心,沒有特別遇過這個情境真沒有想到有如此狀況。
若有其他情境或解法也歡迎大家分享~
參考資料