可為 Null 的參考型別Nullable reference types

C# 8.0 引進可為 Null 的參考型別不可為 Null 的參考型別,可讓您針對參考型別變數的屬性撰寫相關重要陳述式:C# 8.0 introduces nullable reference types and non-nullable reference types that enable you to make important statements about the properties for reference type variables:

  • 參考不應為 null。A reference isn't supposed to be null. 當變數不應該是 null 時,編譯器會強制執行規則,確保在不先檢查變數不是 null 的情況下,就能安全地取值這些變數:When variables aren't supposed to be null, the compiler enforces rules that ensure it's safe to dereference these variables without first checking that it isn't null:
    • 變數必須初始化為非 Null 值。The variable must be initialized to a non-null value.
    • 變數永遠不可指派 null 值。The variable can never be assigned the value null.
  • 參考可能為 NullA reference may be null. 當變數可為 Null 時,編譯器會實施不同的規則,確保您已針對 Null 參考正確地進行檢查:When variables may be null, the compiler enforces different rules to ensure that you've correctly checked for a null reference:
    • 只有在編譯器能保證該值並非為 Null 時,才能對該變數進行取值 (Dereference)。The variable may only be dereferenced when the compiler can guarantee that the value isn't null.
    • 這些變數可使用預設的 null 值初始化,也可以在其他程式碼中指派 null 值。These variables may be initialized with the default null value and may be assigned the value null in other code.

這項新功能對舊版 c # 中的參考變數的處理提供了顯著的好處,因為無法從變數宣告判斷設計意圖。This new feature provides significant benefits over the handling of reference variables in earlier versions of C# where the design intent can't be determined from the variable declaration. 編譯器不針對參考型別的 Null 參考例外狀況提供安全:The compiler didn't provide safety against null reference exceptions for reference types:

  • 參考可為 NullA reference can be null. 當參考型別初始化為 null,或稍後指派給 null 時,編譯器不會發出警告。The compiler doesn't issue warnings when a reference type is initialized to null, or later assigned to null. 當參考這些變數時,編譯器會發出警告,但不含 null 檢查。The compiler issues warnings when these variables are dereferenced without null checks.
  • 參考已假設為並非 NullA reference is assumed to be not null. 編譯器不會在對參考型別進行取值 (Dereference) 時發出任何警告。The compiler doesn't issue any warnings when reference types are dereferenced. 如果變數設定為可能是 null 的運算式,則編譯器會發出警告。The compiler issues warnings if a variable is set to an expression that may be null.

這些警告會在編譯時期發出。These warnings are emitted at compile time. 編譯器不會在可為 null 的內容中加入任何 null 檢查或其他執行時間結構。The compiler doesn't add any null checks or other runtime constructs in a nullable context. 在執行時間,可為 null 的參考和不可為 null 的參考都是相等的。At runtime, a nullable reference and a non-nullable reference are equivalent.

透過新增的可為 Null 參考型別,您可以更清楚地宣告您的意圖。With the addition of nullable reference types, you can declare your intent more clearly. null 值是表示變數並非指向某個值的正確方式。The null value is the correct way to represent that a variable doesn't refer to a value. 請不要使用這項功能來從您的程式碼中移除所有 null 值。Don't use this feature to remove all null values from your code. 相反地,您應該對編譯器及其他閱讀您程式碼之開發人員宣告您的意圖。Rather, you should declare your intent to the compiler and other developers that read your code. 藉由宣告您的意圖,編譯器會在您撰寫的程式碼與該意圖不一致時通知您。By declaring your intent, the compiler informs you when you write code that is inconsistent with that intent.

可為 Null 參考型別的語法與可為 Null 實值型別語法相同:將 ? 附加至變數的型別。A nullable reference type is noted using the same syntax as nullable value types: a ? is appended to the type of the variable. 例如,下列變數宣告代表可為 Null 字串變數,nameFor example, the following variable declaration represents a nullable string variable, name:

string? name;

?未附加至類型名稱的任何變數都是不可為 null 的參考型別Any variable where the ? isn't appended to the type name is a non-nullable reference type. 當您啟用這項功能時,其中包括現有程式碼中的所有參考型別變數。That includes all reference type variables in existing code when you've enabled this feature.

編譯器會使用靜態分析來判斷可為 Null 參考是否已知並非為 Null。The compiler uses static analysis to determine if a nullable reference is known to be non-null. 若您在可為 Null 參考可能為 Null 時對其進行取值 (Dereference),編譯器會警告您。The compiler warns you if you dereference a nullable reference when it may be null. 您可以使用容許運算子後面的變數名稱來覆寫此行為 !You can override this behavior by using the null-forgiving operator ! following a variable name. 例如,若您知道 name 變數並非為 Null,但編譯器卻發出警告,您可以撰寫下列程式碼來覆寫編譯器的分析:For example, if you know the name variable isn't null but the compiler issues a warning, you can write the following code to override the compiler's analysis:

name!.Length;

型別的可 NULL 性Nullability of types

任何參考型別都可擁有四種「可 NULL 性」** 中的其中一種,其描述警告產生的時機:Any reference type can have one of four nullabilities, which describes when warnings are generated:

  • 不可為 null: Null 無法指派給這個類型的變數。Nonnullable: Null can't be assigned to variables of this type. 此型別的變數不需進行 Null 檢查即可進行取值 (Dereference)。Variables of this type don't need to be null-checked before dereferencing.
  • Nullable: null 可以指派給這個類型的變數。Nullable: Null can be assigned to variables of this type. 若沒有事先檢查是否為 null 即對此型別的變數進行取值 (Dereference),即會產生警告。Dereferencing variables of this type without first checking for null causes a warning.
  • 遺忘式:遺忘式是 C # 8.0 之前的狀態。Oblivious: Oblivious is the pre-C# 8.0 state. 此型別的變數可進行取值或指派,且皆不會產生警告。Variables of this type can be dereferenced or assigned without warnings.
  • 未知:一般會針對類型參數,其中條件約束不會告知編譯器,類型必須是可為 null不可為 nullUnknown: Unknown is generally for type parameters where constraints don't tell the compiler that the type must be nullable or nonnullable.

變數宣告中型別的可 NULL 性會由宣告該變數的「可為 Null 內容」** 控制。The nullability of a type in a variable declaration is controlled by the nullable context in which the variable is declared.

可為 Null 內容Nullable contexts

可為 Null 內容可讓您對編譯器解譯參考型別變數的方式進行細部控制。Nullable contexts enable fine-grained control for how the compiler interprets reference type variables. 任何指定之來源行的可為 null 注釋內容為已啟用或已停用。The nullable annotation context of any given source line is either enabled or disabled. 您可以將 C # 8.0 之前的編譯器視為在停用的可為 null 內容中編譯所有程式碼:任何參考型別都可以是 null。You can think of the pre-C# 8.0 compiler as compiling all your code in a disabled nullable context: any reference type may be null. 為 null 警告內容可能也會啟用或停用。The nullable warnings context may also be enabled or disabled. 可為 Null 警告內容會指定編譯器使用其流程分析所產生的警告。The nullable warnings context specifies the warnings generated by the compiler using its flow analysis.

您可以使用 .csproj 檔案中的元素,為專案設定可為 null 注釋內容和可為 null 警告內容 Nullable.csprojThe nullable annotation context and nullable warning context can be set for a project using the Nullable element in your .csproj file. 此項目會設定編譯器解譯型別可 NULL 性的方式及所產生警告。This element configures how the compiler interprets the nullability of types and what warnings are generated. 有效的設定如下:Valid settings are:

  • enable:可為 null 注釋內容已啟用enable: The nullable annotation context is enabled. 可為 Null 警告內容為啟用The nullable warning context is enabled.
    • 參考型別變數 (例如 string) 不可為 Null。Variables of a reference type, string for example, are non-nullable. 啟用所有可 NULL 性警告。All nullability warnings are enabled.
  • warnings:可為 null 注釋內容已停用warnings: The nullable annotation context is disabled. 可為 Null 警告內容為啟用The nullable warning context is enabled.
    • 參考型別變數為遺忘式。Variables of a reference type are oblivious. 啟用所有可 NULL 性警告。All nullability warnings are enabled.
  • annotations:可為 null 注釋內容已啟用annotations: The nullable annotation context is enabled. 可為 Null 警告內容為停用The nullable warning context is disabled.
    • 參考型別的變數(例如字串)不可為 null。Variables of a reference type, string for example, are non-nullable. 停用所有可 NULL 性警告。All nullability warnings are disabled.
  • disable:可為 null 注釋內容已停用disable: The nullable annotation context is disabled. 可為 Null 警告內容為停用The nullable warning context is disabled.
    • 參考型別變數為遺忘式,與先前版本的 C# 相似。Variables of a reference type are oblivious, just like earlier versions of C#. 停用所有可 NULL 性警告。All nullability warnings are disabled.

範例Example:

<Nullable>enable</Nullable>

您也可以使用指示詞,在您專案中的任何位置設定相同內容:You can also use directives to set these same contexts anywhere in your project:

  • #nullable enable:將可為 null 注釋內容和可為 null 警告內容設定為 [已啟用]。#nullable enable: Sets the nullable annotation context and nullable warning context to enabled.
  • #nullable disable:將可為 null 注釋內容和可為 null 警告內容設定為停用#nullable disable: Sets the nullable annotation context and nullable warning context to disabled.
  • #nullable restore:將可為 null 注釋內容和可為 null 警告內容還原至專案設定。#nullable restore: Restores the nullable annotation context and nullable warning context to the project settings.
  • #nullable disable warnings:將可為 null 警告內容設為停用#nullable disable warnings: Set the nullable warning context to disabled.
  • #nullable enable warnings:將可為 null 警告內容設定為 [已啟用]。#nullable enable warnings: Set the nullable warning context to enabled.
  • #nullable restore warnings:將可為 null 警告內容還原至專案設定。#nullable restore warnings: Restores the nullable warning context to the project settings.
  • #nullable disable annotations:將可為 null 注釋內容設定為停用#nullable disable annotations: Set the nullable annotation context to disabled.
  • #nullable enable annotations:將可為 null 注釋內容設定為 [已啟用]。#nullable enable annotations: Set the nullable annotation context to enabled.
  • #nullable restore annotations:將批註警告內容還原至專案設定。#nullable restore annotations: Restores the annotation warning context to the project settings.

預設會停用可為 null 的注釋和警告內容,包括新的專案。By default, nullable annotation and warning contexts are disabled, including new projects. 這表示您現有的程式碼會在不變更的情況下編譯,而不會產生任何新的警告。That means that your existing code compiles without changes and without generating any new warnings.

這些選項提供兩個不同的策略來更新現有的程式碼基底,以使用可為 null 的參考型別。These options provide two distinct strategies to update an existing codebase to use nullable reference types.

可為 Null 註釋內容Nullable annotation context

編譯器會在停用的可為 Null 註釋內容中使用下列規則:The compiler uses the following rules in a disabled nullable annotation context:

  • 您無法在停用的內容中宣告可為 Null 參考。You can't declare nullable references in a disabled context.
  • 可能會為所有參考變數指派 null 值。All reference variables may be assigned a value of null.
  • 當對參考型別的變數進行取值 (Dereference) 時,不會產生任何警告。No warnings are generated when a variable of a reference type is dereferenced.
  • Null 容許運算子不可用於停用內容中。The null-forgiving operator may not be used in a disabled context.

行為與先前版本的 C# 相同。The behavior is the same as previous versions of C#.

編譯器會在啟用的可為 Null 註釋內容中使用下列規則:The compiler uses the following rules in an enabled nullable annotation context:

  • 參考型別的任何變數都是不可為 Null 參考Any variable of a reference type is a non-nullable reference.
  • 任何不可為 Null 參考都可安全地進行取值 (Dereference)。Any non-nullable reference may be dereferenced safely.
  • 任何可為 Null 參考型別 (在變數宣告中的型別後方標註 ?) 都可為 Null。Any nullable reference type (noted by ? after the type in the variable declaration) may be null. 靜態分析會判斷值被取值時,是否已知為非 null。Static analysis determines if the value is known to be non-null when it's dereferenced. 若否,則編譯器會警告您。If not, the compiler warns you.
  • 您可以使用 Null 容許運算子來宣告可為 Null 參考並非為 Null。You can use the null-forgiving operator to declare that a nullable reference isn't null.

在啟用的可為 Null 註釋內容中,? 字元會附加至宣告可為 Null 參考型別的參考型別。In an enabled nullable annotation context, the ? character appended to a reference type declares a nullable reference type. Null 容許運算子 ! 可以附加至運算式,以宣告運算式不是 null。The null-forgiving operator ! may be appended to an expression to declare that the expression isn't null.

可為 Null 警告內容Nullable warning context

可為 Null 警告內容與可為 Null 註釋內容不同。The nullable warning context is distinct from the nullable annotation context. 即使停用新的註釋,仍可啟用警告。Warnings can be enabled even when the new annotations are disabled. 編譯器會使用靜態分析來判斷任何參考的 Null 狀態The compiler uses static flow analysis to determine the null state of any reference. 當並未「停用」*****可為 Null 警告內容*時,Null 狀態不是並非為 Null,就是可能為 NullThe null state is either not null or maybe null when the nullable warning context isn't disabled. 若您在編譯器已判斷其可能為 Null 時對參考進行取值 (Dereference),則編譯器會警告您。If you dereference a reference when the compiler has determined it's maybe null, the compiler warns you. 除非編譯器可判斷下列兩個狀況的其中一種狀況,否則參考的狀態就會是可能為 NullThe state of a reference is maybe null unless the compiler can determine one of two conditions:

  1. 變數已確定指派為並非 Null 的值。The variable has been definitely assigned to a non-null value.
  2. 變數或運算式已在取值 (Dereference) 之前針對 Null 進行檢查。The variable or expression has been checked against null before de-referencing it.

當您在可為 null 警告內容中對可能為 null的變數或運算式取值時,編譯器會產生警告。The compiler generates warnings when you dereference a variable or expression that is maybe null in a nullable warning context. 此外,當不可為 null 參考型別指派給已啟用可為 null 注釋內容中的可能是 null變數或運算式時,編譯器會產生警告。Furthermore, the compiler generates warnings when a nonnullable reference type is assigned to a maybe null variable or expression in an enabled nullable annotation context.

屬性描述 ApiAttributes describe APIs

您可以將屬性新增至 Api,以提供有關引數或傳回值何時可以或不能為 null 的詳細資訊。You add attributes to APIs that provide the compiler more information about when arguments or return values can or can't be null. 您可以在本文中深入瞭解這些屬性,其中涵蓋可為 null 屬性的語言參考。You can learn more about these attributes in our article in the language reference covering the nullable attributes. 這些屬性會在目前和即將發行的版本中新增至 .NET 程式庫。These attributes are being added to .NET libraries over current and upcoming releases. 最常使用的 Api 會先更新。The most commonly used APIs are being updated first.

請參閱See also