一元後綴 ! 運算子是 Null 容許或 Null 隱藏運算子。 在啟用的 可空標註解情境中,使用空寬容運算子抑制前述表達式的所有可空警告。 一元前綴 ! 運算子是邏輯否定運算子。 Null 容忍運算子在執行階段沒有作用。 它只會藉由改變運算式的 null 狀態來影響編譯器的靜態流程分析。 在執行時期,運算式 x! 被計算為基礎運算式 x 的結果。
如需可空參考型別功能的詳細資訊,請參閱可空的參考型別。
C# 語言參考資料記錄了 C# 語言最新版本。 同時也包含即將推出語言版本公開預覽功能的初步文件。
文件中標示了語言最近三個版本或目前公開預覽版中首次引入的任何功能。
小提示
欲查詢某功能何時首次在 C# 中引入,請參閱 C# 語言版本歷史的條目。
範例
空寬容運算子的一個使用案例是測試參數驗證邏輯。 例如,請參考下列類別:
#nullable enable
public class Person
{
public Person(string name) => Name = name ?? throw new ArgumentNullException(nameof(name));
public string Name { get; }
}
透過使用 MSTest 測試框架,你可以在建構子中建立以下驗證邏輯測試:
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public void NullNameShouldThrowTest()
{
var person = new Person(null!);
}
因為缺少 Null 容許運算子,所以編譯器會為上述指令碼產生以下警告:Warning CS8625: Cannot convert null literal to non-nullable reference type。 透過使用空容納運算子,你可以告知編譯器 null 傳遞是預期中的,且不應該產生警告。
當你確定某個表達式不能被 Null null 寬容,但編譯器無法辨識時,也可以使用空寬容運算子。 在以下範例中,如果 IsValid 方法傳回 true,則其引數不會為 null,所以您可以放心對其取值 (Dereference):
public static void Main()
{
Person? p = Find("John");
if (IsValid(p))
{
Console.WriteLine($"Found {p!.Name}");
}
}
public static bool IsValid(Person? person)
=> person is not null && person.Name is not null;
因為缺少 Null 容許運算子,所以編譯器會為p.Name 指令碼產生以下警告:Warning CS8602: Dereference of a possibly null reference。
如果您可以修改 IsValid 方法,則您可以使用 NotNullWhen 屬性來指示編譯器當方法傳回 IsValid 時,null 方法的引數不可能為 true:
public static void Main()
{
Person? p = Find("John");
if (IsValid(p))
{
Console.WriteLine($"Found {p.Name}");
}
}
public static bool IsValid([NotNullWhen(true)] Person? person)
=> person is not null && person.Name is not null;
在前述範例中,您不需要使用 Null 容許運算子,因為編譯器擁有足夠的資訊,可以判斷在 p 陳述式中 null 不可能是 if。 如需詳細資訊以了解能針對變數 Null 狀態提供其他資訊的屬性,請參閱使用屬性升級 API 以定義 Null 預期。
C# 語言規格
如需詳細資訊,請參閱空性容許運算子一節的可為 Null 參考型別規格草稿。