! (null 容許) 運算子 (c # 參考)

在 c # 8.0 和更新版本中提供,一元 ! 後置運算子是 null 容許或 null 隱藏專案運算子。 在啟用的 可為 null 注釋內容中,您可以使用 null 容許運算子來宣告 x 參考型別的運算式不是 nullx! 。 一元前置 ! 運算子是 邏輯負運算子

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!);
}

如果沒有容許運算子,編譯器會針對上述程式碼產生下列警告: Warning CS8625: Cannot convert null literal to non-nullable reference type 。 藉由使用 null 容許運算子,您會通知編譯器必須傳遞 null ,且不應該收到警告。

當您確定運算式不能是, null 但編譯器無法管理來辨識該運算式時,您也可以使用 null 容許運算子。 在下列範例中,如果 IsValid 方法傳回 true ,則其引數不是, null 而且您可以安全地取值:

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;

如果沒有容許運算子,編譯器會為程式碼產生下列警告 p.NameWarning 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 之參考型別規格之草稿的容許運算子一節。

另請參閱