写在前面
本文是 .NET 新特性系列第一篇。.NET 5(2020-11)是"统一 .NET"的第一代——从此去掉 “Core” 后缀,把原来的 .NET Framework + .NET Core + Xamarin 合并为一个平台。
虽然 .NET 5 是非 LTS 的过渡版本,但它带来的 C# 9 特性是划时代的:record、init、顶级语句、模式匹配增强——这些至今是日常代码的基石。从这版起,现代 C# 的面貌基本成型。
一、版本概览
1
2
3
4
5
6
7
8
9
10
11
| .NET 5
发布:2020-11
支持:非 LTS(标准支持 18 个月)
C#:9
定位:统一时代开端
历史意义:
✓ 去掉 "Core" 后缀,统一品牌
✓ Framework + Core + Xamarin 合并为一个 .NET
✓ 一个 BCL、一个运行时、一套工具链服务所有平台
✓ 跳过版本 4(避免和 .NET Framework 4.x 混淆)
|
二、C# 9 语言特性(重点)
2.1 record(记录类型)⭐
C# 9 最重要的特性。一行定义不可变、值相等的"数据类":
1
2
3
4
5
6
7
8
9
10
11
12
| // 一行定义(编译器自动生成属性、构造、相等、ToString、解构)
public record User(int Id, string Name, string Email);
var u1 = new User(1, "张三", "z@test.com");
var u2 = new User(1, "张三", "z@test.com");
u1 == u2; // true(值相等,普通 class 是 false)
u1 with { Name = "李四" }; // with 表达式:复制并改一个字段
var (id, name, _) = u1; // 解构
// 传统 class 要手写一堆:构造、Equals、GetHashCode、ToString、Deconstruct
// record 一行搞定
|
1
2
3
4
5
6
7
| record 的本质:
基于值相等的引用类型(不可变)
自动生成:属性、主构造、Equals/GetHashCode、ToString、Deconstruct
支持 with(非破坏性修改)
适用:DTO、值对象、消息、不可变数据
C# 10 起还有 record struct(值类型版)
|
2.2 init 只读设置器 ⭐
对象初始化后不可修改:
1
2
3
4
5
6
7
8
9
10
11
12
13
| public class User
{
public string Name { get; init; }
public int Age { get; init; }
}
var u = new User { Name = "张三", Age = 25 }; // 初始化时设置
u.Age = 26; // ❌ 编译错误!init 后不可改
// 对比:
// get; set; — 任意读写(不安全)
// get; — 只读(只能在构造里赋值)
// get; init; — 初始化时写,之后只读(两全)
|
1
2
3
4
| init 解决的问题:
对象初始化器(new X { ... })的灵活性
+ 创建后不可变的线程安全
配合 record,是不可变数据建模的核心
|
2.3 顶级语句(top-level statements)⭐
Program.cs 不用写 class 和 Main,直接写代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // C# 9 之前:Program.cs
using System;
namespace MyApp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello");
}
}
}
// C# 9:整个 Program.cs 就一行
System.Console.WriteLine("Hello");
// 还能用 async、args、返回值
var name = args.Length > 0 ? args[0] : "World";
Console.WriteLine($"Hello {name}");
|
1
2
3
4
| 顶级语句大幅简化小程序 / API 入口
编译器自动包成 Main 方法
ASP.NET Core 的 Minimal API 基于此(.NET 6)
大型项目仍可用传统 Main
|
2.4 模式匹配增强
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| // 关系模式(< > <= >=)
static string Grade(int score) => score switch
{
>= 90 => "A",
>= 80 => "B",
>= 60 => "C",
_ => "F"
};
// 逻辑组合(and / or / not)
static bool IsDigit(char c) => c is >= '0' and <= '9';
static bool IsLetter(char c) => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';
// not 模式
if (obj is not null) { } // 比 obj != null 更"模式化"
// 类型 + 条件组合
static decimal GetFee(object o) => o switch
{
int n when n > 100 => 0.5m,
string s => 1.0m,
_ => 2.0m
};
|
2.5 target-typed new(目标类型 new)
省略类型名,由上下文推断:
1
2
3
4
5
6
7
| // 上下文已知类型,new() 即可
Dictionary<string, List<int>> dict = new();
List<User> users = new();
Process(new User(1, "x")); // 参数类型已知,省略
// 对比旧写法:类型名写两遍
Dictionary<string, List<int>> dict = new Dictionary<string, List<int>>();
|
2.6 协变返回类型
重写方法可以返回更具体的派生类型:
1
2
3
4
5
6
7
8
| class Animal
{
public virtual Animal Clone() => new Animal();
}
class Dog : Animal
{
public override Dog Clone() => new Dog(); // 返回 Dog(更具体),合法
}
|
2.7 本地大小整数(nint / nuint)
1
2
3
4
5
| // nint = 平台相关的整数(32位系统是 int,64位是 long)
nint ptr = 123; // 64位系统上是 8 字节
nuint uptr = 456;
// 用于互操作、指针运算(和 IntPtr 对应)
|
2.8 其他
1
2
3
4
5
6
7
8
9
10
11
12
| // 静态匿名 lambda(不捕获,可缓存)
Func<int, int> f = static x => x * 2;
// target-typed 条件表达式(两分支类型不同,但有公共目标类型)
var result = condition ? 1 : 1.5; // 推断为 double
// 函数指针(互操作,比 delegate 快)
delegate* unmanaged<int, int> fp;
// 模块初始化器(程序集加载时执行)
[ModuleInitializer]
internal static void Init() { /* 全局初始化 */ }
|
三、统一平台与运行时
3.1 统一 .NET
1
2
3
4
5
6
7
8
9
10
11
| .NET 5 之前:
.NET Framework(仅 Windows,老)
.NET Core(跨平台,新)
Xamarin/Mono(移动端)
互不兼容,库要分别维护
.NET 5 之后:
一个 .NET 运行所有平台
一个 BCL(基础类库)
一套 SDK / 工具链
库只需写一次,到处跑
|
3.2 Single-file 发布
1
2
3
4
| # 打成单个可执行文件
dotnet publish -c Release -r linux-x64 --self-contained false /p:PublishSingleFile=true
# 一个文件即可运行(无需装运行时,配合 self-contained)
|
3.3 Windows Runtime 支持
1
2
| C#/WinRT:.NET 5 重新支持 Windows Runtime API(UWP、WinUI 互操作)
在 .NET Core 3.x 被移除,5 重新引入(通过 CsWinRT)
|
3.4 性能改进
1
2
3
4
5
| ✓ GC 改进(Gen 0/1 更快)
✓ JIT 改进
✓ ARM64 优化
✓ 异步开销降低
✓ System.Text.Json 性能(追赶 Newtonsoft)
|
四、BCL 改进
1
2
3
4
5
6
7
8
9
| // System.Text.Json 大幅增强(接近生产可用)
// 可空引用类型、记录、异步流
// Half(16位浮点)
Half h = 1.5f;
// System.Text.Json 可靠性提升(默认严格)
// StringComparer 改进、Regex 性能
|
五、升级建议
1
2
3
4
5
6
| .NET 5 已停止支持(2022-05),不应再用于生产
→ 升级到 LTS(6/8/10)
但 C# 9 的特性(record、init、顶级语句):
→ 仍是现代 C# 的核心,日常必用
→ 只要项目 ≥ C# 9(.NET 5+)就能用
|
六、小结
.NET 5 是统一时代的开端:
- 意义:去掉 Core 后缀,Framework+Core+Xamarin 统一
- C# 9(划时代):record、init、顶级语句、模式匹配(and/or/not、关系)、target-typed new、协变返回
- 平台:单一运行时/BCL/SDK,Single-file 发布,Windows Runtime
- 定位:非 LTS 过渡版,但 C# 9 特性奠定现代 C# 基础
下一篇讲 .NET 6(C# 10):首个统一 LTS——全局 using、文件命名空间、record struct、Minimal API。