第五部分:C#最佳实践与展望
第13章:代码优化与设计模式
13.1 性能优化技巧
1. 避免不必要的对象分配
- 字符串操作优化:使用
StringBuilder替代频繁的字符串拼接(+操作符),尤其在循环中。 - 结构体 vs 类:对于小型、不可变的数据,优先使用
struct减少堆内存分配。 - 对象池模式:复用对象(如数据库连接、线程等)以减少 GC 压力。
2. 集合与数据结构的优化
- 选择合适的集合类型:
List<T>:适合随机访问和遍历。Dictionary<TKey, TValue>:适合快速键值查找。Span<T>或Memory<T>:减少数据拷贝,提升内存效率。
- 预分配集合容量:若已知集合大小,初始化时指定容量(如
new List<T>(1000))避免动态扩容开销。
3. 异步与多线程优化
- 避免阻塞调用:使用
async/await替代.Result或.Wait()防止线程死锁。 - 并行化计算:对 CPU 密集型任务使用
Parallel.For或Parallel.ForEach。 - 取消任务:通过
CancellationToken及时终止长时间运行的任务。
4. 内存管理
- Dispose 模式:及时释放非托管资源(文件句柄、数据库连接等),实现
IDisposable接口。 - GC 调优:减少大对象分配(LOH),避免频繁触发 GC。
5. 算法与逻辑优化
- 缓存计算结果:对重复计算使用缓存(如
MemoryCache或字典)。 - 延迟加载:按需初始化资源(如
Lazy<T>)。 - 减少反射:反射性能开销大,可用表达式树或代码生成替代。
6. 性能分析工具
- Visual Studio 诊断工具:分析 CPU 使用率、内存分配等。
- BenchmarkDotNet:精确测量代码性能。
- PerfView:深入分析 .NET 应用性能瓶颈。
示例代码
// 使用 StringBuilder 优化字符串拼接
var sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
sb.Append(i.ToString());
}
string result = sb.ToString();
// 使用 Span<T> 减少内存分配
int[] array = new int[100];
Span<int> span = array.AsSpan();
span.Fill(1); // 无需创建新数组
关键原则
- 测量优先:优化前先用工具定位瓶颈。
- 权衡可读性与性能:避免过度优化导致代码难以维护。
