1) StringBuilder 是什么,什么时候该用
StringBuilder(System.Text)是可变字符串 容器,适合反复拼接/插入/删除/替换 的场景:它允许直接 Append/Insert/Remove/Replace 子串,而不是每次都生成新的 string。
典型应用:循环里拼字符串 、拼大文本 、需要频繁修改局部内容 → 优先 StringBuilder。
StringBuilder 的构造器可以选择接收一个初始字符串值,及内部容量的初始值(默认为16个字符)。
如果需要更大的容量,则 StringBuilder 会自动(以较小的性能代价)调整它的内部结构,以至其最大的容量(默认为 int.MaxValue )。
2) 核心属性与索引器
Length
- 当前内容长度(字符数)。
- 清空内容:可以
sb.Length = 0(但注意容量不变)。
Capacity(容量)
- 内部缓冲区容量;构造器可指定初始容量,默认 16 个字符。
- 容量不足会自动扩容(有一定性能代价),最大默认可到
int.MaxValue。
索引器 sb[i]
- 可读写单个字符(按字符位修改)。
3) 常用方法(按用途分组)
构建/追加
Append(...):追加字符串/数字/字符等(最常用)。AppendLine(...):追加后再追加换行(Windows 下\r\n)。AppendFormat(...):格式化追加,类似string.Format。
局部编辑
Insert(index, value):在指定位置插入。Remove(startIndex, length):删除一段。Replace(oldValue, newValue):替换(语义同string.Replace)。
生成最终字符串
ToString():得到最终string结果。
清空与复用
sb.Length = 0只清内容,不释放容量;曾经装过 100 万字符,清空后仍可能占用约 2MB 内存。- 真想释放内存:new 一个新的 StringBuilder,让旧对象离开作用域等待 GC。
4) 应用场景(代码示例)
场景 1:循环拼接大文本(日志/CSV/SQL)
典型用法就是循环
Append,最后ToString()。
csharp
using System;
using System.Text;
class Demo
{
static void Main()
{
var sb = new StringBuilder();
for (int i = 0; i < 100; i++)
{
sb.Append(i).Append(","); // 链式追加
}
// 去掉最后一个逗号(演示 Remove)
if (sb.Length > 0) sb.Remove(sb.Length - 1, 1);
string csvLine = sb.ToString();
Console.WriteLine(csvLine);
}
}
场景 2:预估长度、提前设定容量,降低扩容成本
构造器可给初始字符串/初始容量;默认容量 16,不够会扩容。
csharp
using System.Text;
int rowCount = 20000;
int avgRowLen = 40;
// 预估容量:避免在循环里频繁扩容
var sb = new StringBuilder(capacity: rowCount * avgRowLen);
for (int i = 0; i < rowCount; i++)
{
sb.Append("Row=").Append(i).AppendLine();
}
string text = sb.ToString();
场景 3:局部插入/替换(模板渲染、协议报文、动态文本)
csharp
using System;
using System.Text;
var sb = new StringBuilder("Hello NAME, today is DATE.");
sb.Replace("NAME", "Ritchie");
sb.Replace("DATE", DateTime.Today.ToString("yyyy-MM-dd"));
sb.Insert(0, "[INFO] "); // 头部插入
sb.Remove(sb.Length - 1, 1); // 删除末尾句点
Console.WriteLine(sb.ToString());
场景 4:按字符修改(索引器)
StringBuilder有可写索引器,可以直接改某一位字符。
csharp
using System;
using System.Text;
var sb = new StringBuilder("A1C3E5");
for (int i = 1; i < sb.Length; i += 2)
{
sb[i] = '*'; // 把奇数位替换为 *
}
Console.WriteLine(sb); // A*C*E*
场景 5:复用 vs 释放内存(你写长期运行程序时很关键)
sb.Length=0不会减小容量;要释放容量需 new 新对象。
csharp
using System.Text;
// 复用:适合高频、短文本(避免频繁分配)
var sb = new StringBuilder(1024);
sb.Append("...大量拼接...");
sb.Length = 0; // 清空但不释放容量
// 释放:曾经装过超大文本,想把内存还给系统
sb = new StringBuilder(); // 换新对象,旧对象可被 GC 回收