Skip to Content
MUZINET-NOTE 4.0 is released 🎉
技术知识库C#字符串不可变性与StringBuilder

🧩 string 是引用类型,却“像值类型”?

在 C# 中,string 属于 引用类型System.String),但它具备值语义:你“修改”字符串时,并不会改动原对象,而是创建一个新的字符串实例。这就是 不可变(Immutable) 的含义,也是很多人觉得它“像值类型”的原因。

✨ 一个直观例子

string a = "hello"; string b = a; b = "world"; Console.WriteLine(a); // hello Console.WriteLine(b); // world

由于不可变,b 重新指向了一个新的 "world" 实例,而 a 仍然指向原来的 "hello" 实例。


⚠️ 频繁拼接的性能隐患

当你在循环里用 + 或插值拼接字符串时,每一次“修改”都会分配新对象,带来多余的内存分配GC 压力。在日志构建、HTML 片段拼接、长文本生成等场景,性能会明显下降。


🚀 更高效的选择:StringBuilder

StringBuilder 内部维护可扩展缓冲区,就地修改、减少对象创建,适合大量/频繁拼接的场景。

using System.Text; var sb = new StringBuilder(); sb.Append("Hello"); sb.Append(", "); sb.Append("World!"); sb.Append(" 👋"); string result = sb.ToString(); // "Hello, World! 👋"

🔁 循环场景对比

// ❌ 低效:每次拼接都创建新字符串 string s = string.Empty; for (int i = 0; i < 1000; i++) { s += i + ","; } // ✅ 高效:缓冲区就地扩展 var sb2 = new StringBuilder(capacity: 4096); // 预估容量可进一步减少扩容 for (int i = 0; i < 1000; i++) { _ = sb2.Append(i).Append(','); } string s2 = sb2.ToString();

🧭 选择建议

  • 少量拼接/一次性生成:直接用 string 或字符串插值(可读性最好)。
  • 大量/循环拼接:优先 StringBuilder(可预估容量时设置 capacity)。
  • 格式化复杂模板string.Create(高级用法)或 StringBuilder.AppendFormat
  • 不可变带来的好处:线程安全(引用层面)、易缓存、易比较(驻留/Intern 可能生效)。

📌 小结对照表

场景/特性string(不可变)StringBuilder(可变)
类型引用类型(值语义表现)引用类型(缓冲区可变)
修改开销创建新对象就地修改,少分配
适用场景少量拼接、常量、配置、键名大量拼接、循环生成、日志
可读性⭐⭐⭐⭐⭐⭐⭐
性能(大量拼接)⭐⭐⭐⭐

🗣 一句话记忆

小量用 string,大量用 StringBuilder;一次性用插值,循环里用缓冲。


🔚 结语

理解 string 的不可变性,你就理解了 C# 字符串的内存与性能模型。 在合适的场景使用 StringBuilder,能显著减少分配、提升吞吐,让你的 .NET 服务更稳更快。


© MUZINET · 有客赞 | 分享 .NET / C# 与现代架构实践

最后更新于