SuperAPI AI 工具集

type-design-performance

编程与开发

查看项目

更新于 10-15 10:26

技能介绍

用途

该技能用于在 .NET 中设计类型与 API 时兼顾性能,适用于设计新类型和 API、审查代码中的性能问题、在 class、struct 与 record 之间做选择,以及处理集合与可枚举对象等场景。

主要能力

默认密封类

除非明确为继承而设计,否则应密封类。密封类可让 JIT 进行去虚拟化,并传达“这不是扩展点”的 API 意图,同时防止意外的破坏性变更。record 本质是类,同样应密封。

值类型使用 readonly struct

不可变的结构体应声明为 readonly,以防止防御性拷贝。适用于小型、短生命周期的数据。文档给出 struct 与 class 的选用对照:struct 适合小(通常 ≤16 字节)、短生命周期、频繁分配、需要值语义、不可变的场景;class 适合较大对象、长生命周期、需要共享引用、需要标识语义、可变状态的场景。

优先静态纯函数

无副作用的静态方法更快且更易测试:没有虚表查找、没有隐藏状态、纯输入到输出便于测试、天然线程安全、强制显式依赖。文档同时提醒不要过度使用,当确实需要状态或多态时应使用实例方法。

延迟枚举

在必要时才物化可枚举对象,避免过长的 LINQ 链和多次 ToList。若调用方可能不需要全部元素,可返回 IEnumerable 由调用方决定何时物化。

异步枚举

避免在 LINQ 中直接使用 async(会为每个元素产生 Task 分配),推荐使用 IAsyncEnumerable 进行流式处理,或对并行场景使用批量处理。

ValueTask 与 Task

在经常同步完成的热路径上使用 ValueTask 以避免分配;真正的 I/O 操作直接使用 Task。ValueTask 规则:不要多次 await 同一个 ValueTask;不要在完成前使用 .Result 或 .GetAwaiter().GetResult();如有疑问就用 Task。

Span 与 Memory

底层字节操作使用 Span<T> 和 Memory<T> 而非 byte[]。同步操作接受 Span,异步操作接受 Memory。常见模式包括无分配切片、stackalloc 小缓冲区、ArrayPool 租用较大缓冲区。

集合返回类型

从 API 边界返回不可变集合(如 IReadOnlyList<T>),避免调用方修改内部状态。静态查找数据可使用 .NET 8+ 的 FrozenDictionary、FrozenSet。内部构建时使用可变 List,返回时以只读形式暴露。文档给出返回类型对照:API 边界用 IReadOnlyList<T>、IReadOnlyCollection<T>;静态查找数据用 FrozenDictionary<K,V>、FrozenSet<T>;内部构建用 List<T> 再以只读返回;单个或没有用 T?;零个或多个且惰性用 IEnumerable<T>。

使用方式

该技能以指导原则、代码示例与对照表的形式呈现,供在设计与审查 .NET 代码时参照。文档未提供安装命令或具体调用步骤,暂未提供。

适用场景

设计新的 .NET 类型与 API、审查代码性能、在 class/struct/record 间做选择、处理集合与可枚举对象、编写异步与底层字节处理代码。

限制

文档未说明该技能的运行环境、依赖版本或平台限制,暂未提供。部分建议(如 FrozenDictionary)标注需要 .NET 8+。文档提醒不要过度使用静态纯函数,需要状态或多态时应使用实例方法。

反模式

文档列出的反模式包括:无理由的不密封类、可变结构体、本可静态化的实例方法、多次 ToList 调用、从公共 API 返回 List<T>、对始终异步的操作使用 ValueTask。

资源

性能最佳实践:https://learn.microsoft.com/en-us/dotnet/standard/performance/

Span 指南:https://learn.microsoft.com/en-us/dotnet/standard/memory-and-spans/

冻结集合:https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen