.NET 10之可空引用类型

C# 8.0 引入了 可空引用类型(Nullable Reference Types) 功能。这项特性通过使得开发者显式标注哪些引用类型可以为 null,旨在减少程序中的 NullReferenceException 错误,从而提高代码的健壮性和可维护性。下面将深入讲解可空引用类型的功能、特点、使用场景及其设置方法。

1. 基本概念

在 C# 中,引用类型(如 string, object)通常是可以为 null 的。传统的 C# 编程模型中,引用类型变量默认可以被赋值为 null,这会导致空引用异常(NullReferenceException)等问题。

启用可空引用类型后:
  1. 非可空引用类型 :这些类型不能为 null,必须始终引用一个有效的对象。如果赋值为 null,编译器会发出错误或警告。

  2. 可空引用类型 :这些类型显式声明可以为 null,并且编译器会允许为 null,但在使用它们时仍然需要显式处理。

2. 启用与禁用可空引用类型

2.1 启用 #nullable enable

通过在代码文件顶部添加 #nullable enable,可以启用可空引用类型特性:

csharp 复制代码
#nullable enable

启用后,所有引用类型(如 string, object)默认变为非可空类型 ,必须始终引用有效对象。如果某个引用类型可以为 null,需要显式地使用 ? 语法标注。

csharp 复制代码
#nullable enable

string name = "John";  // 允许赋值有效的字符串
name = null;  // 编译错误,因为 `string` 默认不可为 null

string? nullableName = null;  // 允许为 null
2.2 禁用 #nullable disable

通过在代码中使用 #nullable disable,可以禁用可空引用类型的检查,恢复默认行为,使所有引用类型均可以为 null

csharp 复制代码
#nullable disable

string name = null;  // 允许为 null,默认行为
2.3 在项目文件中启用

你还可以通过修改 .csproj 项目文件全局启用可空引用类型,而不必在每个 C# 文件中添加 #nullable enable

xml 复制代码
<PropertyGroup>
  <Nullable>enable</Nullable>
</PropertyGroup>

这样会对整个项目启用可空引用类型,简化配置。

3. 可空引用类型的行为与特性

启用可空引用类型后,C# 编译器会根据不同的引用类型是否显式声明为可空类型(?)来做出不同的处理。

3.1 默认行为:非可空引用类型

默认情况下,引用类型不能为 null,编译器会强制要求引用类型变量在使用前被赋值,并且不允许赋值为 null

csharp 复制代码
#nullable enable

string name = "Alice";  // 正常,不为 null
name = null;  // 编译错误:无法将 null 分配给非可空引用类型
3.2 可空引用类型:使用 ? 标注

当你明确希望某个引用类型可以为 null 时,可以在类型后加上 ?,声明该类型为可空类型。这时,编译器不会警告你该引用可能为 null,但你需要显式地进行 null 检查。

csharp 复制代码
#nullable enable

string? name = null;  // 正常,允许为 null
3.3 对方法返回类型的影响

可空引用类型特性也影响方法返回值的处理。如果方法返回一个引用类型,且该引用类型可以为 null,则需要显式声明返回值为可空类型。

csharp 复制代码
#nullable enable

public string? GetGreeting(bool isMorning)
{
    if (isMorning)
    {
        return "Good Morning!";
    }
    return null;  // 返回值为 null,合法
}

如果返回类型为非可空引用类型,则不能返回 null,否则会报编译错误。

3.4 Null 检查:编译时警告

启用可空引用类型后,编译器会提示开发者在使用可能为 null 的变量时进行 null 检查。否则,编译器会发出警告,提醒开发者可能存在空引用错误。

csharp 复制代码
#nullable enable

public void PrintLength(string? input)
{
    Console.WriteLine(input.Length);  // 编译警告:可能会引发 NullReferenceException
}

为了避免此类错误,你需要显式地检查 input 是否为 null

csharp 复制代码
if (input != null)
{
    Console.WriteLine(input.Length);  // 安全访问
}
3.5 Nullable enable 的局部作用域

#nullable enable 可以在局部范围内启用或禁用,比如在某个方法中启用可空引用类型,外部则不受影响:

csharp 复制代码
#nullable enable

public void ExampleMethod()
{
    string name = "John";  // 正常,不为 null

    #nullable disable
    string? nullableName = null;  // 允许为 null

    #nullable enable
    string greeting = "Hello";  // 重新启用,非 null
}

4. 使用场景

4.1 提高代码的安全性与健壮性

启用可空引用类型最直接的好处是减少因 NullReferenceException 导致的运行时错误。由于 C# 编译器会强制你处理可能为 null 的引用类型,开发者在编写代码时会更加小心,减少空引用错误的发生。

例如,避免常见的空引用错误:

csharp 复制代码
public void PrintLength(string? input)
{
    if (input == null)
    {
        Console.WriteLine("Input is null");
    }
    else
    {
        Console.WriteLine(input.Length);  // 安全地使用 input
    }
}
4.2 增强代码可维护性与可读性

通过显式标注哪些类型可以为 null,可以增强代码的可读性,使得后续维护人员更加容易理解代码的行为。

  • string 类型显式表示非空:string name;(不允许 null
  • string? 类型显式表示可空:string? name;(允许 null
4.3 适用于大型团队和项目

在大型团队和复杂项目中,启用可空引用类型有助于确保团队成员遵循一致的规则来处理 null 值,减少因为空值错误导致的潜在漏洞,确保更高的代码质量。

4.4 与现有代码兼容

启用可空引用类型特性后,可以逐步进行迁移,逐步修复和处理空引用问题。在早期阶段,你可以先启用该特性,然后逐步解决代码中的 null 引用问题,而不会因为改动过多导致破坏现有代码。

5. 总结

C# 中的可空引用类型是对引用类型的增强,旨在提高代码的健壮性、可维护性,并减少常见的空引用错误。通过启用 #nullable enable,开发者可以显式指定哪些引用类型可以为 null,并且编译器会强制要求进行必要的 null 检查,减少潜在的运行时错误。

  • 启用与禁用 :通过 #nullable enable#nullable disable 控制。
  • 作用域控制:可以在方法或类级别启用或禁用。
  • 使用场景:适用于大型项目、团队协作以及现有代码迁移,旨在提高代码质量和减少错误。
相关推荐
月挽清风2 小时前
代码随想录第十四天
数据结构
long3162 小时前
Z算法(线性时间模式搜索算法)
java·数据结构·spring boot·后端·算法·排序算法
码云数智-园园2 小时前
基于 JSON 配置的 .NET 桌面应用自动更新实现指南
.net
无风听海2 小时前
.NET 10 之dotnet run的功能
.net
岩屿2 小时前
Ubuntu下安装Docker并部署.NET API(二)
运维·docker·容器·.net
码云数智-大飞2 小时前
.NET 中高效实现 List 集合去重的多种方法详解
.net
easyboot2 小时前
使用tinyply.net保存ply格式点云
.net
张人玉2 小时前
WPF 多语言实现完整笔记(.NET 4.7.2)
笔记·.net·wpf·多语言实现·多语言适配
啊阿狸不会拉杆3 小时前
《机器学习导论》第 2 章-监督学习
数据结构·人工智能·python·学习·算法·机器学习·监督学习