你可能忽视的 C# 性能优化细节
在日常开发中,C# 提供了优雅的语法和丰富的特性,让我们能够快速构建功能。但在高并发或大数据量场景下,某些“看似无害”的写法,可能暗中拖累性能。
本文总结了 C# 常见的性能陷阱,帮你快速避坑。
1. string 拼接
字符串在 C# 中是 不可变对象,每次拼接都会分配新的内存。
// ❌ 循环拼接 = O(n²) 复杂度
string result = "";
for (int i = 0; i < 1000; i++)
result += i;
// ✅ StringBuilder 更高效
var sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
sb.Append(i);
string result = sb.ToString();
📌 建议:
- • 小规模拼接 →
+或字符串插值即可。 - • 大规模循环拼接 →
StringBuilder。
2. LINQ vs for 循环
LINQ 简洁,但性能有代价:它会创建迭代器对象,并产生额外的方法调用。
// ❌ LINQ 在高频场景下可能偏慢
var sum = numbers.Where(x => x % 2 == 0).Sum();
// ✅ for 循环更高效
int sum = 0;
for (int i = 0; i < numbers.Length; i++)
if (numbers[i] % 2 == 0) sum += numbers[i];
📌 建议:
- • 性能敏感场景用
for/foreach。 - • 业务逻辑清晰优先时用 LINQ。
3. 装箱与拆箱
装箱就是把值类型(int、struct)转成 object,拆箱再转回来。
// ❌ 装箱/拆箱开销大
object obj = 42; // 装箱
int x = (int)obj; // 拆箱
// ✅ 用泛型避免装箱
List<int> list = new List<int>();
list.Add(42);
📌 建议:
- • 高频操作尽量避免
object/ 非泛型集合。 - • 使用泛型(如
List<T>、Dictionary<K,V>)。
4. 值类型 vs 引用类型
值类型(struct)分配在栈上,引用类型(class)在堆上。如果 struct 太大,频繁复制会拖慢性能。
// ❌ 大 struct 会导致频繁复制
struct BigStruct { public int A, B, C, D, E, F, G, H; }
// ✅ 用 class 或只定义小 struct
class BigClass { public int A, B, C, D, E, F, G, H; }
📌 建议:
- • struct 小而轻(如 Point、Vector3)时使用。
- • 大对象、复杂对象 → class。
5. 异常处理的滥用
异常的开销远大于 if 判断。
// ❌ 不要用异常代替逻辑控制
try
{
int x = int.Parse("abc");
}
catch { }
// ✅ TryParse 更高效
if (int.TryParse("abc", out var value)) { }
📌 建议:
- • 异常用于真正的异常场景。
6. async/await 的额外开销
async/await 会生成状态机对象,带来分配。
// ❌ 无意义 async
public async Task<int> GetValueAsync() => 42;
// ✅ 用 ValueTask
public ValueTask<int> GetValueAsync() => new(42);
📌 建议:
- • 高频调用的短方法 →
ValueTask。 - • 避免“无意义 async”。
7. 不合理的集合选择
不同集合适用场景不同。
| 集合类型 | 优势 | 不适合场景 |
| List | 随机访问快 | 中间频繁插入/删除 |
| Dictionary<K,V> | 查找 O(1) | 小数据量开销大 |
| LinkedList | 插入/删除快 | 遍历慢 |
| HashSet | 去重/集合运算 | 顺序敏感场景 |
| Queue/Stack | FIFO/LIFO 高效 | 随机访问 |
8. 闭包(Closure)的隐形分配
闭包会导致捕获的变量提升到堆上。
// ❌ 产生闭包
int counter = 0;
Func<int> f = () => counter++;
// ✅ 避免闭包
int Increment(int x) => x + 1;
📌 建议:
- • 高频循环避免创建闭包。
9. 大对象分配
大于 85KB 的对象会进 大对象堆,GC 成本高。
// ❌ 每次分配大数组
byte[] buffer = new byte[100_000];
// ✅ 用 ArrayPool
var buffer = ArrayPool<byte>.Shared.Rent(100_000);
ArrayPool<byte>.Shared.Return(buffer);
🔟 频繁调用 DateTime.Now
DateTime.Now 每次都会访问系统时钟。
// ❌ 高频调用
for (int i = 0; i < 1_000_000; i++)
var t = DateTime.Now;
// ✅ 缓存一次
var now = DateTime.Now;
📌 建议:
- • 高性能场景用
Stopwatch。
1️⃣1️⃣ 滥用 ToList()
ToList() 会强制枚举并分配内存。
// ❌ 多余的 ToList()
var evens = numbers.Where(x => x % 2 == 0).ToList();
// ✅ 延迟执行更高效
foreach (var n in numbers.Where(x => x % 2 == 0))
Console.WriteLine(n);
最后
性能优化不是“过早优化”,而是 避免无意识的性能陷阱。
当应用规模变大、并发量上升时,这些小细节可能决定系统能否扛住压力。
🚀 记住:写代码先保证清晰易读,遇到瓶颈时再结合这些技巧优化。

浙公网安备 33010602011771号