1. 入门
提醒一下,C#里的字符串是 不可变的(immutable)。意思就是,字符串一旦创建就不能改:所有看起来像是“修改”字符串的操作,其实都是在内存里新建了一个字符串。
比如你写:
string hello = "你好";
hello += " 世界!"; // 看着像hello变了,其实是新对象!
变量 hello 指向了一个新对象,旧的(如果没别的地方用)迟早会被垃圾回收器干掉。如果你在循环里反复这么搞,内存就会被“塞爆”,性能会突然暴跌。尤其是你要拼接成千上万的字符串时:每一步都新建一个字符串,所有字符都要复制,旧对象等着被回收,程序突然就卡成狗。
这时候,今天的主角就该登场了——StringBuilder。
using System.Text; // ← 必须加!
StringBuilder sb = new StringBuilder("你好");
sb.Append(" 世界!"); // 现在字符串改得又快又省心<
认识 StringBuilder
StringBuilder 是 System.Text 命名空间下的一个类。它的任务就是高效地拼接和组装大字符串,可以直接改内容,不用老是新建对象。
打个比方:
如果说字符串(string)像一块拼图板,每次只能整个换掉,那 StringBuilder 就像磁性画板,随便你贴贴撕撕,不用每次加点内容都换新画板。
啥时候该用 StringBuilder?
- 你要反复改字符串(尤其是在循环里)。
- 你要把很多小片段拼成一大段文本。
- 你在意速度和内存用量。
啥时候不用?
- 你只做一两次简单的字符串操作——用普通 string 更简单更直观。
- 你真的(不知道为啥)想保存每个字符串的中间状态。
2. 创建和基本操作 StringBuilder
引入命名空间
很简单,别忘了加命名空间。
using System.Text;// ← 必须加!
创建新字符串的几种方式
StringBuilder sb1 = new StringBuilder(); // 空的
StringBuilder sb2 = new StringBuilder("开始"); // 有初始内容
StringBuilder sb3 = new StringBuilder(100); // 预留100个字符
常用方法
var sb = new StringBuilder("开头");
sb.Append(" + 加了新内容"); // 末尾加内容
sb.AppendLine("(这个带换行)"); // 加内容并换行
sb.Insert(0, "起始: "); // 从0位置插入
sb.Remove(0, 7); // 从0删7个字符
sb.Replace("内容", "STRING"); // 把所有"内容"换成"STRING"
string result = sb.ToString(); // 得到最终字符串
3. StringBuilder 的效率
例子:性能对比
假如你要把 10 000 个数字拼成一个字符串(比如老师让你输出全班同学学号):
天真写法(string)
string text = "";
for (int i = 0; i < 10000; i++)
{
text += i + " "; // 每次都新建字符串!
}
Console.WriteLine(text.Substring(0, 100) + "..."); // 只输出前100个
高效写法(StringBuilder)
var sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
sb.Append(i).Append(' '); // 可以链式写!
}
Console.WriteLine(sb.ToString().Substring(0, 100) + "...");
区别在哪?
第一个写法会慢很多,还可能吃掉更多内存。第二个又快又省内存。
4. StringBuilder 最常用的方法
Append —— 加字符串或别的类型(会自动转成字符串):
sb.Append("内容");
sb.Append(123); // 123会变成"123"
sb.Append('!'); // 单个字符
AppendLine —— 加字符串+换行:
sb.AppendLine("一行"); // 会加"一行\n"
Insert —— 在指定位置插入字符串:
sb.Insert(0, "Hello, "); // 插到最前面
Remove —— 删除几个字符:
sb.Remove(3, 4); // 从第3位开始删4个字符
Replace —— 替换所有子串或字符:
sb.Replace("old", "new");
sb.Replace('a', 'A');
ToString —— 返回最终字符串。
截断字符串
和 string 不一样,StringBuilder 对象可以直接设置新长度,字符串会被截断到这个长度。
sb.Length = 10; // 超过10的都没了!
5. 使用细节和常见坑
为啥 ToString() 很重要
你用 StringBuilder 的时候,手里拿的不是字符串,而是个特殊对象。很多方法(比如 Console.WriteLine)能自动把它转成字符串,但有时候会踩坑——比如你不小心和普通字符串比较,或者写了类似:
if (sb == "你好") { ... } // 哎呀!就算sb里是"你好"也不行
结果会是 false:其实比较的是不同类型的对象。
正确写法:
if (sb.ToString() == "你好") { ... }
可变性
和 string 不同,StringBuilder 是可变的(mutable)!一个对象内容可以随便改,这就是它快的原因。
用完别忘了 ToString(),否则你拿到的不是字符串,而是像 System.Text.StringBuilder 这样的神秘文本。
缓冲区大小和自动扩容
StringBuilder 里面其实是个字符数组。如果你提前知道要拼很长的字符串,可以在构造函数里传个预期长度——这样会快一点。
var bigBuilder = new StringBuilder(50000); // 预计5万个字符
不过就算你估错了也没事!StringBuilder 会自动扩容,只是会慢一点点。
内存溢出?
理论上,如果你完全不克制,拼接几十亿字符,也可能遇到 OutOfMemoryException,但实际开发里基本不会遇到。
GO TO FULL VERSION