StringBuilder仅在循环追加、动态长度、高频拼接时优于+或$"";≤3次固定拼接用+/$""更优;需预估容量、避免ToString()滥用、禁用Replace/Remove等非追加操作。

StringBuilder 不是“一用就快”,而是“用错就慢”——它只在循环追加、动态长度、高频拼接场景下明显优于 + 或 $"";拼 2–3 次固定字符串时,+ 反而更快、更轻量。
什么时候该用 StringBuilder,什么时候该用 + 或 $""
判断依据不是“要不要拼字符串”,而是“拼的次数和模式”:
- 拼接次数 ≤ 3 次,且内容基本来自常量或局部变量 → 直接用
+或$"";编译器会优化成string.Concat,零额外开销 - 循环内拼接(哪怕只有 2 个字段),或拼接次数不确定(如日志行累积、HTML 片段生成、SQL 参数拼装)→ 必须用
StringBuilder - 单次拼接含 5+ 个片段,或任意片段长度 > 100 字符 → 建议上
StringBuilder,避免临时字符串堆压 - 拼完即弃、且长度极短(如调试日志中的小状态码)→ 用
Span<char>+stackalloc更轻量,但仅限栈分配安全场景
StringBuilder.Append() 的参数类型真会影响性能
传 int、bool、DateTime 等值类型时,别先调 .ToString():
- 错:
sb.Append(value.ToString())→ 触发装箱 + 新字符串分配 - 对:
sb.Append(value)→ 内部走无分配格式化路径(如Append(Int32)直接写入数字字符) - 拼分隔符也别偷懒:
sb.Append(", ")比sb.AppendLine()少一次换行符判断;若你明确要\n就用sb.Append("\n"),别为“跨平台”牺牲确定性 - 数组拼接优先用
sb.AppendJoin(", ", list),比手写foreach+Append少 2–3 层方法调用开销
初始化容量和 ToString() 调用时机是最大性能陷阱
new StringBuilder() 默认初始容量仅 16,循环中极易触发多次扩容(每次约 1.5 倍复制):
- 预估长度:比如拼 1000 条日志,每条平均 80 字符 → 初始化
new StringBuilder(80_000),宁可略高估 -
ToString()是深拷贝操作:内部char[]全量复制到新string对象;1MB 内容拷贝耗时明显 - 严禁在循环里调
ToString()查看中间结果;调试用sb.Length和sb.Capacity,快百倍 - 复用实例时用
sb.Clear(),但它不释放底层数组;若后续拼接规模骤变(如从 KB 突增到 MB),不如新建更稳
别把 StringBuilder 当文本编辑器用
它的设计契约是“只追加”,所有破坏这一前提的操作都会退化为 O(n) 搬移:
-
Replace()、Remove()、Insert()出现,说明逻辑该前置 —— 比如制表符替换,应在塞进StringBuilder前用line.Replace("\t", " ") - 需要频繁删改中间内容?换
List<string>+string.Join(),或者直接用string配合正则 - 所有非追加操作,本质都是在掩盖字符串建模错误:你本不该在拼接中途修改语义
最常被忽略的一点:不是“用了 StringBuilder 就算优化了”,而是“是否让追加行为真正连续、无中断、无回溯”。一旦出现 Replace 或循环内 ToString,性能收益几乎归零。



















