stringbuilder仅在循环追加、动态长度、高频拼接时优于+;≤3次固定拼接用+或$""更优;需预估容量、避免循环中tostring()、慎用replace/remove等破坏追加语义的操作。

StringBuilder 不是“一用就快”,而是“用对才快”——它只在循环追加、动态长度、高频拼接场景下碾压 +;拼 2–3 个固定字符串时,+ 反而更快。
什么时候该 new StringBuilder(),什么时候直接用 + 或 $""
判断依据不是“要不要拼字符串”,而是“拼的次数和模式”:
- 拼接次数 ≤ 3 次,且内容基本来自常量或局部变量 → 直接用
+或$"";编译器会优化成string.Concat,零额外开销 - 循环内拼接(哪怕只有 2 个字段),或拼接次数不确定(如日志行累积、HTML 片段生成、SQL 参数拼装)→ 必须用
StringBuilder - 单次拼接含 5+ 个片段,或任意片段长度 > 100 字符 → 建议上
StringBuilder,避免临时字符串堆压 - 拼完即弃、且长度极短(如调试日志中的小状态码)→ 用
Span<char></char>+stackalloc更轻量,但仅限栈分配安全场景
StringBuilder.Append() 的参数类型真会影响性能
传 int、bool、DateTime 等值类型时,别先调 .ToString():
- 错:
sb.Append(value.ToString())→ 触发装箱 + 新字符串分配 - 对:
sb.Append(value)→ 内部走无分配格式化路径(如Append(Int32)直接写入数字字符) - 拼分隔符也别偷懒:
sb.Append(", ")比sb.AppendLine()少一次换行符判断,若你明确要\n就用Append("\n"),别为“跨平台”牺牲确定性 - 数组拼接优先用
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>+string.Join(),或者直接用string配合正则 -
AppendLine()适合写文件/日志等需标准换行的场景;但若目标是 HTTP 响应体(必须\n),就别依赖它自动适配 - 多线程共用一个
StringBuilder实例?不行 —— 它不是线程安全的;每个线程自己 new 一个,或用ThreadLocal<stringbuilder></stringbuilder>
真正难的不是记住 API,而是每次写拼接逻辑前,问一句:这段代码会在请求链路里跑多少次?如果答案是“每秒上百”,那 StringBuilder 的初始化容量、Append 参数类型、ToString 时机,一个都不能错。











