可为空引用类型Nullable reference types

C#8.0 引入了“可为空引用类型”和“不可为空引用类型”,使你能够对引用类型变量的属性作出重要声明 :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.
    • 变量永远不能赋值为 nullThe variable can never be assigned the value null.
  • 引用可为 null。A reference may be null. 当变量可以为 null 时,编译器会强制执行不同的规则以确保你已正确检查空引用:When variables may be null, the compiler enforces different rules to ensure that you've correctly checked for a null reference:
    • 只有当编译器可以保证该值不为 null 时,才可以取消引用该变量。The variable may only be dereferenced when the compiler can guarantee that the value isn't null.
    • 这些变量可以使用默认的 null 值进行初始化,也可以在其他代码中赋值为 nullThese 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. 编译器不提供针对引用类型的空引用异常的安全性:The compiler didn't provide safety against null reference exceptions for reference types:

  • 引用可为 null。A 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.
  • 假定引用不为 null。A reference is assumed to be not null. 当引用类型被取消引用时,编译器不会发出任何警告。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.

通过添加可为空引用类型,你可以更清楚地声明你的意图。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.

使用与可为空值类型相同的语法记录可为空引用类型:将 ? 附加到变量的类型。A nullable reference type is noted using the same syntax as nullable value types: a ? is appended to the type of the variable. 例如,以下变量声明表示可为空的字符串变量 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。The compiler uses static analysis to determine if a nullable reference is known to be non-null. 如果你在一个可为空引用可能是 null 时对其取消引用,编译器将向你发出警告。The compiler warns you if you dereference a nullable reference when it may be null. 可以通过使用 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 分配给此类型的变量。Nonnullable: Null can't be assigned to variables of this type. 在取消引用之前,无需对此类型的变量进行 null 检查。Variables of this type don't need to be null-checked before dereferencing.
  • 可为空:可将 null 分配给此类型的变量。Nullable: Null can be assigned to variables of this type. 在不首先检查 null 的情况下取消引用此类型的变量时发出警告。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”或“不可为 null” 。Unknown: Unknown is generally for type parameters where constraints don't tell the compiler that the type must be nullable or nonnullable.

变量声明中类型的为 Null 性由声明变量的“可为空上下文”控制。The nullability of a type in a variable declaration is controlled by the nullable context in which the variable is declared.

可为空上下文Nullable contexts

可为空上下文可以对编译器如何解释引用类型变量进行精细控制。Nullable contexts enable fine-grained control for how the compiler interprets reference type variables. 可以启用或禁用任何给定源代码行的“可为空注释上下文”。The nullable annotation context of any given source line is either enabled or disabled. 可以将 C# 8.0 之前的编译器视为在禁用的可为空上下文中编译所有代码:任何引用类型都可以为空。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. 还可以启用或禁用可为空警告上下文。The nullable warnings context may also be enabled or disabled. 可为空警告上下文指定编译器使用其流分析生成的警告。The nullable warnings context specifies the warnings generated by the compiler using its flow analysis.

可以使用 .csproj 文件中的 Nullable 元素为项目设置可为空注释上下文和可为空警告上下文。The 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:“启用”可为空注释上下文。enable: The nullable annotation context is enabled. “启用”可为空警告上下文。The nullable warning context is enabled.
    • 引用类型的变量,例如 string 是“不可为空”。Variables of a reference type, string for example, are non-nullable. 启用所有为 Null 性警告。All nullability warnings are enabled.
  • warnings:“禁用”可为空注释上下文。warnings: The nullable annotation context is disabled. “启用”可为空警告上下文。The nullable warning context is enabled.
    • 引用类型的变量是“无视”。Variables of a reference type are oblivious. 启用所有为 Null 性警告。All nullability warnings are enabled.
  • annotations:“启用”可为空注释上下文。annotations: The nullable annotation context is enabled. “禁用”可为空警告上下文。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:“禁用”可为空注释上下文。disable: The nullable annotation context is disabled. “禁用”可为空警告上下文。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:将可为空注释上下文和可为空警告上下文设置为“已启用”。#nullable enable: Sets the nullable annotation context and nullable warning context to enabled.
  • #nullable disable:将可为空注释上下文和可为空警告上下文设置为“已禁用”。#nullable disable: Sets the nullable annotation context and nullable warning context to disabled.
  • #nullable restore:将可为空注释上下文和可为空警告上下文还原到项目设置。#nullable restore: Restores the nullable annotation context and nullable warning context to the project settings.
  • #nullable disable warnings:将可为空警告上下文设置为“已禁用”。#nullable disable warnings: Set the nullable warning context to disabled.
  • #nullable enable warnings:将可为空警告上下文设置为“已启用”。#nullable enable warnings: Set the nullable warning context to enabled.
  • #nullable restore warnings:将可为空警告上下文还原到项目设置。#nullable restore warnings: Restores the nullable warning context to the project settings.
  • #nullable disable annotations:将可为空注释上下文设置为“禁用”。#nullable disable annotations: Set the nullable annotation context to disabled.
  • #nullable enable annotations:将可为空注释上下文设置为“启用”。#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.

默认情况下,可为空注释和警告上下文处于禁用状态,包括新项目。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.

可为空注释上下文Nullable annotation context

编译器在已禁用的可为空注释上下文中使用以下规则:The compiler uses the following rules in a disabled nullable annotation context:

  • 不能在已禁用的上下文中声明可为空引用。You can't declare nullable references in a disabled context.
  • 可以为所有引用变量分配 null 值。All reference variables may be assigned a value of null.
  • 取消引用引用类型的变量时不会生成警告。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#.

编译器在已启用的可为空注释上下文中使用以下规则:The compiler uses the following rules in an enabled nullable annotation context:

  • 引用类型的任何变量都是“不可为空引用”。Any variable of a reference type is a non-nullable reference.
  • 任何不可为空引用都可以安全地取消引用。Any non-nullable reference may be dereferenced safely.
  • 任何可为空引用类型(在变量声明中的类型之后由 ? 标记)可为 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。You can use the null-forgiving operator to declare that a nullable reference isn't 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.

可为空警告上下文Nullable warning context

可为空警告上下文与可为空注释上下文不同。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” 。The null state is either not null or maybe null when the nullable warning context isn't disabled. 如果在编译器确定引用“可能为 null”时取消引用该引用,编译器会向你发出警告。If you dereference a reference when the compiler has determined it's maybe null, the compiler warns you. 除非编译器可以确定以下两个条件之一,否则引用的状态为“可能为 null”:The 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. 在取消引用之前,已检查变量或表达式是否为 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 变量或表达式时,编译器会生成警告。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 或不可为 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