! (null-forgiving) 運算子 (C# 參考)
一元後綴 !
運算子是 Null 容許或 Null 隱藏運算子。 在已啟用可為 Null 的註釋內容中,您可以使用 Null 容許運算子來為上述運算式隱藏所有可為 Null 的警告。 一元前綴 !
運算子是邏輯否定運算子。 Null 容許運算子在執行階段沒有作用, 其只會藉由變更運算子的 Null 狀態來影響編譯器的靜態流量分析。 在執行階段,運算式 x!
會評估為基礎運算式 x
的結果。
如需可為 Null 參考型別功能的詳細資訊,請參閱可為 Null 的參考型別。
範例
Null 容許運算子的其中一個使用案例,是用於測試引數驗證邏輯。 例如,請參考下列類別:
#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
但編譯器無法認知這點時,您也可以使用 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 屬性來指示編譯器當方法傳回 true
時,IsValid
方法的引數不可能為 null
:
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
在 if
陳述式中不可能為 null
。 如需詳細資訊以了解能針對變數 Null 狀態提供其他資訊的屬性,請參閱使用屬性升級 API 以定義 Null 預期。
C# 語言規格
如需詳細資訊,請參閱可為 Null 參考型別規格的草稿的 Null 容許運算子一節。