C# 9.0 核心新特性详解:Init-only Setters、Records 与顶级语句

星野
星野
发布时间:2026-10-16 | 4人浏览过
原创

在 .NET 5.0 统一框架的背景下,C# 9.0 带来了一系列旨在精简代码、强化不可变性并提升开发效率的新特性。本文将详细解读 Init-only setters、Records、Top-level statements 以及增强的 Pattern matching 四大核心功能,助您快速掌握现代 C# 的最佳实践。

Init-only Setters (初始化设置器)

在 C# 9.0 之前,若要实例化具有只读属性的对象,通常必须在构造函数中通过参数赋值。虽然这样可以保证不可变性,但在使用对象初始值设定项(Object Initializers)时往往不够灵活。
C# 9.0 引入了 init 关键字,允许在对象创建期间对只读属性进行初始化赋值,且在赋值完成后即变为只读。

第1步:定义使用 Init 的属性类

目的: 创建一个包含不可变字段和可变字段的类,演示 init 的行为约束。
操作: 使用 get; init; 语法定义属性。
对比参考代码:

class Customers
{
public int CustomerId { get; }
public string CustomerName { get; set; }

public Customers(int customerId)
{
CustomerId = customerId;
}

static void Main(string[] args)
{
var customers = new Customers(1045)
{
CustomerName = "Tyson"
};

// customerid 不能设置,因为该属性是只读
customers.CustomerId = 1099;
}
}

第2步:应用 Init-only Setters 优化代码

动作: 将 CustomerId 修改为支持初始化的属性。
结果: 可以在对象初始值设定项中直接赋值,且后续无法修改。
示例代码:

class Customers
{
public int CustomerId { get; init; }
public string CustomerName { get; set; }

static void Main(string[] args)
{
var customers = new Customers()
{
CustomerId = 1045,
CustomerName = "Tyson"
};

// CS8852: 只能在对象初始值设定项中或在实例构造函数或...分配
customers.CustomerId = 1099;
}
}

Records (记录类型)

Records 是一种专为表示数据的引用类型设计的特性。它默认提供基于值的相等比较、自动生成 ToString() 方法,并支持通过 with 表达式轻松创建对象副本(Copy-on-Write),极大减少了样板代码。

第1步:传统方式处理对象状态变更

背景: 在没有 Record 时,需要手动拷贝所有属性以生成“修改后”的新对象。
示例代码:

class SalesOrder
{
public int OrderId { get; init; }
public string ProductName { get; init; }
public int Quantity { get; init; }

static void Main(string[] args)
{
SalesOrder order = new SalesOrder { OrderId = 1, ProductName = "Mobile", Quantity = 2 };

// 修改ProductName,需手动构造新对象
SalesOrder newOrder = new SalesOrder { OrderId = order.OrderId, ProductName = "Laptop", Quantity = order.Quantity };
}
}

第2步:使用 Record 简化克隆逻辑

入口: 使用 record 关键字声明类型。
动作: 利用 with 表达式创建继承原值并修改指定属性的新记录。
优势: 代码更直观,无需关心内部属性的逐个赋值。

public record SalesOrder
{
public int OrderId { get; init; }
public string ProductName { get; init; }
public int Quantity { get; init; }

static void Main(string[] args)
{
SalesOrder order = new SalesOrder { OrderId = 1, ProductName = "Mobile", Quantity = 2 };

// 使用 with 表达式创建副本并修改属性
SalesOrder newOrder = order with { ProductName = "Laptop" };
}
}

Top-level Statements (顶级语句)

为了降低入门门槛并简化控制台脚本类应用的编写,C# 9.0 允许直接在文件顶层编写执行代码,编译器会自动将其包装到隐藏的 Program.Main 方法中。这被称为脚本模式。

第1步:理解传统结构

场景: 打印一行欢迎语通常需要命名空间、类定义和 Main 方法签名。
参考代码:

using System;

namespace CSharp9
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Welcome!");
}
}
}

第2步:启用顶级语句

动作: 直接书写 Console.WriteLine。
可观察状态: 代码依然能正常编译运行,隐藏了繁重的脚手架代码。
简化代码:

using System;

Console.WriteLine("Welcome !");

如果项目严格限制不使用顶级语句,也可显式调用:

System.Console.WriteLine("Welcome !");

Pattern Matching (模式匹配) 增强

C# 9.0 扩展了模式匹配能力,新增了关系模式(Relational Patterns)和逻辑模式(Logical Patterns),使得在 switch 表达式中进行复杂条件判断更加自然。

  • 关系模式: 支持使用 <, <=, >, >= 等运算符进行大小比较。

  • 逻辑模式: 支持使用 and, or, not 组合多个条件。

第1步:构建使用新模式匹配的类

入口: 在方法中使用 switch 表达式。
动作: 结合数值范围判断(如 < 1000)和逻辑分组(如 500 or 600)返回不同结果。
完整示例:

public class SalesOrder
{
public int OrderId { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public int TotalCost { get; set; }

public double GetTotalCost() => TotalCost switch
{
500 or 600 => 10,
< 1000 => 10 * 1.5,
<= 10000 => 10 * 3,
_ => 10 * 5
};
}

class CSharpFeatures
{
static void Main(string[] args)
{
SalesOrder newOrderforCustomer1 = new SalesOrder() { OrderId = 1, ProductName = "Camera", Quantity = 1, TotalCost = 5000 };
newOrderforCustomer1.GetTotalCost();
SalesOrder newOrderforCustomer2 = new SalesOrder() { OrderId = 2, ProductName = "Pen", Quantity = 1, TotalCost = 500 };
newOrderforCustomer2.GetTotalCost();
}
}

总结

C# 9.0 通过上述四个核心特性,显著提升了开发人员处理数据的便利性。Init-only setters 让不可变对象的初始化更安全简洁;Records 极大地减少了数据模型的样板代码;Top-level statements 让小型脚本不再繁琐;而增强的模式匹配则让条件分支逻辑更加清晰易读。

以上就是 C# 9.0 推出的4个新特性的详细内容,更多关于 C# 语言进阶的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表