
我深耕.NET技术栈十余年,专注于C#代码优化,深知普通开发者与高性能工程师之间的差距往往源于对细节的把控。性能优化并非依赖最新硬件或盲目扩展,而是从编码之初就贯彻高效原则。
以下是20条性能优化技巧——既有常见实践,也有少为人知的秘技。它们将助你的.NET应用运行更快、内存消耗更低,展现真正的企业级表现。
反复使用+或+=拼接字符串是经典错误。C#字符串不可变,每次拼接都会创建新对象。改用StringBuilder:
var sb = new StringBuilder();
for (int i = ; i < ; i++)
{
sb.Append("Hello ");
}
string result = sb.ToString();此方法避免内存过度分配和垃圾回收压力。
LINQ虽提升可读性,但可能引入性能开销。例如:
var max = numbers.Max(); // 遍历集合两次!改为简单循环:
int max = int.MinValue;
foreach (var num in numbers)
{
if (num > max) max = num;
} 大数据集下,此优化效果显著。
List<T>虽灵活,但动态扩容有开销。已知元素数量时用数组:
int[] numbers = new int[]; // 消除扩容开销操作大数组或字符串时,Span<T>避免冗余内存分配:
Span<int> span = new int[] { , , , }; // 切片无需创建新数组值类型与object互转会触发堆分配。优先用泛型保持类型安全:
object obj = ; // 装箱 → 性能损失
int num = (int)obj; // 拆箱 → 性能损失并行任务利用多核优势:
Parallel.For(, , i => ProcessItem(i)); 无需返回UI线程时,始终添加:
await SomeAsyncMethod().ConfigureAwait(false); // 避免上下文切换async void难以处理异常。始终返回Task:
async Task DoWorkAsync() { } 字典的O(1)查找远胜列表遍历:
var dict = new Dictionary<int, string>();
dict[] = "First";
string value = dict[]; readonly结构体减少复制开销:
readonly struct Point { public int X { get; } public int Y { get; } } 抛出异常代价高昂。勿用:
try { int value = dict[key]; } catch { } 改用:
if (dict.TryGetValue(key, out int value)) { } 将计算密集型任务移至后台线程:
await Task.Run(() => ComputeHeavyTask()); 在连接字符串中启用池化复用连接:
"Server=myServer;Database=myDB;User Id=myUser;Password=myPass;Pooling=true;" 简单数据模型用结构体减少堆分配:
struct Employee { public int Id; public string Name; } 临时小数组直接在栈上分配:
Span<int> numbers = stackalloc int[]; 避免新建线程,改用线程池:
ThreadPool.QueueUserWorkItem(_ => ProcessData()); 处理大对象时减少内存碎片:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; 用Lazy<T>推迟昂贵操作:
private static readonly Lazy<MyService> _service = new(() => new MyService()); 大数据集异步逐条生成:
async IAsyncEnumerable<int> GetNumbers()
{
for (int i = ; i < ; i++)
yield return i;
} 勿盲目优化!用工具定位瓶颈: