小提示
本文屬於 基礎部分, 適合已經至少懂一種程式語言並正在學習 C# 的開發者。 如果你是程式新手,建議先從 入門 教學開始。
你是從 Java 還是 C++ 轉過來? C# 透過可空性參考型別提供編譯時的 null 安全。 這個目標類似於 Java 的 @NonNull 註解,但由編譯器強制執行。 C# 也有專用的運算子,比如 ?. 和 ?? ,讓空安全表達式變得簡潔。
null 代表不存在一個值。 當你嘗試透過呼叫方法或讀取屬性來存取參考中的成員 null 時,執行時會拋出一個 NullReferenceException:
// Accessing a member on null throws NullReferenceException at runtime:
// string? name = null;
// int length = name.Length; // throws NullReferenceException
// Check before you dereference:
string? name = null;
if (name is not null)
{
Console.WriteLine($"Name has {name.Length} characters.");
}
else
{
Console.WriteLine("Name has no value.");
}
// Output: Name has no value.
C# 提供三種互補工具來撰寫空安全程式碼:
-
可空值類型:讓像
int或bool這樣的值類型也能持有null -
可控參考類型:使編譯器能夠追蹤參考是否可能為
null - 空運算子:簡潔地表達空安全存取與備援邏輯
可為 Null 的實值型別
預設情況下,像 int、double 和 bool 這樣的值類型無法持有 null。 在型別名稱中加入 ? 以建立 一個可空的值型別 ,該值可包含 或 null:
int? score = null;
Console.WriteLine(score.HasValue); // False
score = 95;
Console.WriteLine(score.HasValue); // True
Console.WriteLine(score.GetValueOrDefault()); // 95
int? missing = null;
Console.WriteLine(missing.GetValueOrDefault(-1)); // -1
當底層值類型需要代表「無資料」時,可空值型別非常有用。常見的情況包括可能缺失的資料庫欄位、可選的設定,以及尚未被捕捉到的感測器讀數。
關於宣告、檢查與轉換的完整說明,請參見 Nullable value types。
可為空的參考類型
參考型別,如 string、陣列和類別實例,可以在執行時保持 null 。
可空參考型別 是編譯器的功能,能明確表示空意圖並在編譯時捕捉錯誤。
透過使用 ? 註解,你宣告了你的意圖:
-
string?—這個參考可能是null;如果你未先檢查就解引用,編譯器會發出警告。 -
string— 此參考 不應該 是null;編譯器會在你指派null時警告
// string? means this reference might be null
// string means this reference should not be null
string? nullableName = null;
string nonNullName = "Alice";
// ?. safely accesses a member when the reference might be null
string display = nullableName?.ToUpper() ?? "(no name)";
Console.WriteLine(display); // (no name)
display = nonNullName.ToUpper(); // safe: nonNullName is never null
Console.WriteLine(display); // ALICE
所有最新 SDK 範本所建立的 .NET 專案預設會啟用可為 null 的參考型別。 欲了解啟用與註解的完整指引,請參見 可空參考類型。
零運算元
C# 包含數個運算子,使你能撰寫安全的 null 程式碼,而不需要在各處手動設定 ifnull 檢查。
| 操作員 | Name | Purpose |
|---|---|---|
?. |
空條件成員存取 | 只有當物件非空時才存取成員 |
?[] |
空條件索引器存取 | 只有當集合非空時才存取元素 |
?? |
零聚合 | 返回預設值當表達式為null |
??= |
空值合併賦值運算 | 僅在變數為 null 時進行指定 |
is null / is not null |
Null 模式 | 偏好的零檢定 |
string? city = GetCity();
// ?. — access a member only when non-null
int? len = city?.Length;
// ?? — substitute a default when null
string display = city ?? "unknown";
// is null — preferred null test
if (city is null)
{
Console.WriteLine("No city provided.");
}
else
{
Console.WriteLine($"{display} ({len} chars)");
}
// Output: No city provided.
關於每個運算子的詳細範例,請參見 空運算子。
可空值型別與可空參考型別有不同的用途
可空值型別和可空參考型別不是替代方案。 它們解決了不同的問題:
- 用
T?表示「無值」的值類型。例如,int?可用於可選的資料庫欄位,而DateTime?則適用於尚未排程的事件。 - 使用
string?及其他可為 null 的參考註解來說明某個參考可能為,這樣編譯器就能在執行階段發生null前提醒你。
這些功能與 null 運算子結合,提供了完整的工具組合來撰寫 null 安全的 C# 程式碼。