性能优化应避免循环内创建对象、慎用LINQ、减少装箱拆箱、区分I/O与CPU密集型异步操作,并优先使用分析工具定位真实热点。

避免在循环里反复创建对象
频繁的堆分配会触发 GC,尤其在高频调用路径(如游戏帧更新、网络包解析)中,new List 或 new StringBuilder() 放在循环内是典型性能雷区。
实操建议:
- 把对象声明提到循环外,复用实例(注意线程安全——若非并发场景,直接复用;若多线程,考虑
ThreadLocal或对象池) - 对短生命周期字符串拼接,优先用
string.Concat()或string.Join(),而非循环中+= - 用
Span替代ArraySegment或临时数组,避免堆分配(例如解析字节流时用Span).Slice()
慎用 LINQ 方法链
Where().Select().ToList() 看起来简洁,但每层都生成新迭代器 + 多次遍历 + 额外装箱(对值类型),在热路径中开销明显。
实操建议:
- 简单过滤/映射直接写 for 循环:索引访问快、无委托调用开销、无状态机生成
- 必须用 LINQ 时,优先选
AsEnumerable()前的原生集合方法(如List、.FindAll() .ConvertAll()),它们是泛型实现,无装箱 -
Count()别用于已知长度的集合——直接用.Count属性;Any()比Count() > 0快得多
减少装箱和拆箱
对 int、DateTime 等值类型调用 object.ToString()、存入 ArrayList 或传给接受 object 的旧 API,都会触发装箱——分配堆内存并拷贝值。
实操建议:
- 用泛型集合替代非泛型:
List而非ArrayList,Dictionary而非Hashtable - 日志或调试输出时,避免隐式装箱:用
$"Value: {i}"(编译为string.Format重载)比"Value: " + i更优(后者触发i.ToString()装箱) - 自定义结构体上别轻易加虚方法或实现接口(除非必要),否则传参/赋值可能隐式装箱
异步 I/O 不要盲目用 Task.Run
把同步文件读取、JSON 解析等 CPU 密集操作包进 Task.Run(() => {...}),看似“异步”,实则只是把线程池线程占住,还增加调度开销,对吞吐无益反损。
实操建议:
- I/O 密集操作(HTTP 请求、数据库查询、文件读写)优先用真正的异步方法:
HttpClient.GetAsync()、FileStream.ReadAsync()、JsonSerializer.DeserializeAsync() - CPU 密集任务(图像处理、加密计算)才考虑
Task.Run,且需评估是否真需要并行——有时单线程 SIMD 指令(如Vector)更高效 - 避免在
async void方法里做耗时工作;不要用.Result或.Wait()阻塞异步任务,易死锁
var stream = File.OpenRead("data.json");
// ✅ 正确:真正异步反序列化
var obj = await JsonSerializer.DeserializeAsync(stream);
// ❌ 错误:同步读+阻塞式反序列化+额外线程调度
var bytes = await File.ReadAllBytesAsync("data.json");
var obj = JsonSerializer.Deserialize(bytes); // 同步CPU密集操作
实际优化时,先用 dotnet-trace 或 Visual Studio Profiler 抓热点,再针对性改。很多“技巧”在低频逻辑里毫无意义,反而让代码难懂。











