string.Replace() 是绝大多数场景的首选,安全、高效、行为可预测;需忽略大小写或模式匹配时才用 Regex.Replace() 并正确转义;链式替换易出错,应改用正则一次性处理;超大文本优化才考虑 Span 或 StringBuilder。

直接用 string.Replace() 就够了,别绕弯
绝大多数场景下,string.Replace() 是最简单、最安全、性能也足够好的选择。它区分大小写、不支持正则、只做字面量替换——这反而是优点:行为可预测,不会因特殊字符意外出错。
常见误用是拿它处理含正则元字符的字符串(比如想替换 "a.b" 却写了 Regex.Replace()),结果发现点号被当通配符;或者在循环里反复调用 Replace() 拼接字符串,导致大量临时对象。其实单次调用就完成全部替换,不需要自己循环。
-
"hello world".Replace("world", "C#")→"hello C#" - 原字符串不含目标子串时,返回原字符串引用,不分配新对象
- 第二个参数为
null会抛ArgumentNullException,空字符串""是合法的(替换成空)
需要忽略大小写?用 Regex.Replace() 配 RegexOptions.IgnoreCase
string.Replace() 没有忽略大小写的重载,硬要实现就得先转成统一大小写再替换——但这样会破坏原字符串大小写结构(比如把 "XML" 全转小写再换,结果变 "json" 而不是 "JSON")。这时候必须上正则。
注意:正则引擎默认对 .、*、+ 等字符有特殊含义,如果只是想替换字面量字符串,得先用 Regex.Escape() 转义:
string input = "a.b+c";
string pattern = Regex.Escape("a.b"); // → "a\.b"
string result = Regex.Replace(input, pattern, "x", RegexOptions.IgnoreCase); // → "x+c"
- 不用
Regex.Escape()直接传"a.b",会匹配任意两个字符(中间是任意单字符),不是你想要的字面量替换 -
RegexOptions.Compiled在频繁调用时可提升性能,但首次编译开销大,短生命周期字符串不建议加 - 正则替换比
string.Replace()慢一个数量级,仅在真需模式匹配或忽略大小写时用
批量替换多个不同值?别写 for 循环,用 Dictionary + 正则
有人习惯这么干:s = s.Replace("a", "x").Replace("b", "y").Replace("c", "z")——问题在于,如果 "x" 本身含 "b",第二次 Replace() 会把它又替成 "y",造成意外交互。正确做法是一次性扫描、按顺序匹配并替换。
核心思路:把所有待替换项构建成正则分支模式(如 "a|b|c"),用 Regex.Replace() 的匹配委托回调决定替换值:
var map = new Dictionary<string string> { ["a"] = "x", ["b"] = "y", ["c"] = "z" };
string pattern = string.Join("|", map.Keys.Select(Regex.Escape));
string result = Regex.Replace(input, pattern, match => map[match.Value]);</string>
- 必须用
Regex.Escape()处理每个 key,否则键含正则字符会崩 - 字典 key 的顺序不保证,若替换有依赖(如先换
"aa"再换"a"),得用SortedDictionary或手动排序 key 数组 - 这个方案仍比链式
Replace()安全,且性能差距不大,10 个以内替换项完全无压力
超长文本或内存敏感场景?考虑 Span + 手动遍历
当字符串长达几 MB、且替换频繁发生(如日志处理器),string.Replace() 每次都新建字符串,GC 压力明显。此时可改用 Span 原地操作,避免分配:
原理是把源字符串转成 Span,用 IndexOf() 找位置,用 MemoryExtensions.Replace()(.NET 5+)或手动拷贝拼接。但注意:Span 不能跨方法返回,且目标替换内容长度变化时无法真正“原地”,最终仍要构造新字符串。
- .NET 6+ 推荐用
StringBuilder配合Span查找:先算总长度,再预分配StringBuilder容量,避免多次扩容 - 自己手写循环时,务必检查越界(
index + search.Length > span.Length),否则Span抛IndexOutOfRangeException - 这种优化只在明确性能瓶颈时才值得做,日常业务代码优先选
string.Replace()
实际项目里,95% 的字符串替换用 string.Replace() 就行;剩下 5% 中,多数是忘了转义正则字符,或者没意识到链式调用的副作用。真正需要 Span 或自定义算法的,往往早该换存储格式(比如用结构化日志代替字符串模板)了。











