.NET 新特性(三):.NET 7(C# 11)表达力提升

写在前面

本文是 .NET 新特性系列第三篇。.NET 7(2022-11)是非 LTS 版,但 C# 11 的表达力大幅提升:原始字符串、列表模式、required、generic math——这些让代码更简洁、更安全、更强大。

运行时方面,Dynamic PGO 默认开启,性能继续攀升。


一、版本概览

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.NET 7
  发布:2022-11
  支持:非 LTS(标准支持 18 个月)
  C#:11
  定位:表达力提升 + 性能打磨

  特点:
    ✓ C# 11 语法大跃进(原始字符串、列表模式、required)
    ✓ Dynamic PGO 默认开启
    ✓ 限流、输出缓存等 ASP.NET Core 中间件

二、C# 11 语言特性(重点)

2.1 原始字符串字面量(raw string literals)⭐

三引号 """ 包裹,无需转义,跨多行,写正则/JSON/HTML 爽:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 不用转义引号、反斜杠
var json = """
{
  "name": "张三",
  "regex": "\\d+"
}
""";

// 插值用多个 $($$ 表示字面 { 一个)
var json2 = $$"""
{
  "id": {{userId}}
}
""";

// 写正则特别爽
var pattern = """\d{4}-\d{2}-\d{2}""";

2.2 列表模式(list patterns)⭐

匹配数组的结构和元素:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
int[] arr = { 1, 2, 3 };

// 匹配固定结构
_ = arr is [1, 2, 3];           // true
_ = arr is [1, .., 3];          // true(.. 匹配中间任意个)
_ = arr is [_, _, _];           // 长度 3

// 解构
if (arr is [var first, .. var middle, var last])
{
    // first=1, middle=[2], last=3
}

// switch
string Desc(int[] a) => a switch
{
    [] => "空",
    [single] => $"一个:{single}",
    [a, b] => $"两个:{a},{b}",
    [..] => "更多"
};

2.3 required 成员 ⭐

强制属性在构造时必须初始化:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class User
{
    public required int Id { get; init; }       // 必须初始化
    public required string Name { get; init; }  // 必须初始化
    public string? Email { get; init; }
}

var u = new User();                       // ❌ 编译错误:缺 Id、Name
var u2 = new User { Id = 1, Name = "x" }; // ✅ 必填项已提供

// 比 [Required](运行时验证)更强:编译期保证

2.4 generic math(静态抽象接口成员)⭐

接口可以有 static abstract 成员,让泛型数学运算成为可能:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 以前:无法对泛型 T 做 T + T(没有运算符约束)
// C# 11:通过 static abstract 接口

// 内置:INumber<T>, IAdditionOperators<T,T,T> 等
static T Sum<T>(params T[] values) where T : INumber<T>
{
    T sum = T.Zero;
    foreach (var v in values) sum += v;   // 泛型类型也能 + 运算了!
    return sum;
}

Sum(1, 2, 3);          // int: 6
Sum(1.5, 2.5);         // double: 4.0

// 自己定义运算符接口
public interface IAddable<T> where T : IAddable<T>
{
    static abstract T operator +(T a, T b);
}
1
2
3
4
意义:
  以前泛型数学要写一堆重载 / 用 dynamic(性能差)
  现在 INumber<T> 约束,一套代码处理所有数值类型
  数值算法、向量运算极大受益

2.5 文件范围类型(file-scoped types)

类型只在当前文件可见:

1
2
3
4
5
file class InternalHelper { }   // 只在本 .cs 文件可见

// 解决:
//  同一程序集多个文件想定义同名辅助类
//  或想限制类型可见性到单文件

2.6 UTF-8 字符串字面量

1
2
3
4
// u8 后缀:直接得到 UTF-8 字节(byte[]),不用 Encoding.GetBytes
byte[] bytes = "Hello"u8;        // new byte[]{ 72, 101, ... }

// 网络协议、文件 IO 常需 UTF-8,省去运行时转换

2.7 其他

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// ref struct 放宽(可用作泛型参数,配合 Span)
// Span<char> 模式匹配
// checked 运算符(自定义 checked 版本)
// generic attributes(泛型特性)
public class MyAttr<T> : Attribute { }

// new() 在泛型约束
static T Create<T>() where T : new() => new T();

// nameof 作用域扩展

三、运行时与性能

3.1 Dynamic PGO 默认开启

1
2
3
4
5
.NET 6 引入 PGO 雏形,.NET 7 默认开启并增强:
  运行时收集热点方法的 profile(分支走向)
  重新编译时基于真实数据优化(内联、分支预测)
  
  实际应用性能提升 5~20%(无需改代码)

3.2 On-Stack Replacement (OSR)

1
2
3
4
方法正在执行中(长循环)也能从 tier 0 升级到 tier 1
  以前:方法要重新调用才优化
  现在:长时间运行的方法中途也能优化
  利好长任务、循环密集代码

3.3 AOT 改进

1
2
NativeAOT 实验性改进(.NET 8 才正式)
publish AOT 持续优化

3.4 其他

1
2
3
4
✓ JIT 改进(更多优化)
✓ 异步改进
✓ 反射性能(源生成器 代替)
✓ ARM64、LoongArch 支持

四、BCL 改进

4.1 CollectionsMarshal

1
2
3
4
5
// 拿到 Dictionary 内部值的引用(避免拷贝、可原地改)
ref int val = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists);
val += 1;   // 直接改字典内值,无拷贝

// 高性能字典操作

4.2 其他

1
2
3
4
5
// Tar 类(读写 tar 归档)
// System.Text.Json:多态(polymorphic)部分支持
// Microsoft.Extensions.* 改进
// Random.Shared(线程安全随机)
// DateOnly/TimeOnly 增强

五、ASP.NET Core 7

5.1 速率限制中间件(Rate Limiter)

1
2
3
4
5
6
builder.Services.AddRateLimiter(o =>
{
    o.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(...);
    o.AddPolicy("per-ip", ctx => ...);
});
app.UseRateLimiter();

5.2 输出缓存(Output Cache)

1
2
3
4
builder.Services.AddOutputCache();
app.UseOutputCache();

app.MapGet("/hot", () => GetData()).CacheOutput(t => t.Expire(TimeSpan.FromMinutes(1)));

5.3 其他

1
2
3
4
✓ MTLS(双向 TLS)支持
✓ HTTP/3
✓ OpenAPI 改进
✓ SignalR / Blazor 改进

六、升级建议

1
2
3
4
5
6
.NET 7 已停止支持(2024-05),非 LTS 不适合长期生产
  → 升级到 8(LTS)

但 C# 11 特性(原始字符串、列表模式、required、generic math):
  → 项目 ≥ 7 即可用,强烈推荐
  → 原始字符串 + 列表模式 + required 是日常高频特性

七、小结

.NET 7 是表达力提升的一版:

  • C# 11:原始字符串(""")、列表模式、required、generic math(static abstract 接口)、file 类型、UTF-8 字面量
  • 运行时:Dynamic PGO 默认开启、OSR
  • BCL:CollectionsMarshal、Tar、Random.Shared
  • ASP.NET Core:限流中间件、输出缓存、MTLS、HTTP/3
  • 定位:非 LTS,但 C# 11 特性极有价值

下一篇讲 .NET 8(C# 12):主构造函数、集合表达式、NativeAOT 正式——成熟的一代 LTS。