c#字符串所有操作均返回新对象,原字符串不可变;频繁拼接必须用stringbuilder;substring严格校验边界,空/null需预检;replace全局区分大小写;split分隔符顺序影响结果;所有方法不修改原串,须显式赋值。

直接说结论:C#字符串所有操作都返回新对象,原字符串不会被修改;频繁拼接别用 + 或 string.Concat,该上 StringBuilder 就上。
为什么 Substring 会抛 ArgumentOutOfRangeException
Substring 不是“取子串”那么简单,它严格校验索引边界。只要 startIndex 超出 0 到 str.Length 之间,或 length 导致越界(即 startIndex + length > str.Length),就炸。
- 常见错误:对空字符串或 null 调用
Substring—— 先用string.IsNullOrEmpty()检查 - 安全写法:用
str.AsSpan().Slice(startIndex, length).ToString()(.NET 5+),它不分配新字符串且越界时抛IndexOutOfRangeException更明确 - 如果只是想“取前 N 位”,推荐
str.Substring(0, Math.Min(N, str.Length)),避免硬编码导致崩
Replace 是全局替换,且区分大小写
Replace 默认把所有匹配项全干掉,不支持正则、不支持次数限制、默认大小写敏感——这是最容易踩的盲区。
- 想只换第一个?得自己写循环 +
IndexOf+Substring拼接,或者用Regex.Replace(str, pattern, replacement, RegexOptions.None, TimeSpan.FromMilliseconds(100))配合count=1 - 想忽略大小写?没有内置参数,必须用
Regex.Replace(str, Regex.Escape(oldValue), newValue, RegexOptions.IgnoreCase) - 注意:
Replace("a", "b")对"aaa"返回"bbb",不是"ba";它不重叠匹配,也不回溯
Split 的分隔符顺序和空项控制很关键
Split 看似简单,但分隔符数组里元素的顺序、是否保留空项、用 char 还是 string 分隔,结果天差地别。
- 用
new char[] { ' ', '\t', '\n' }分隔时,任意一个字符出现就切,且连续分隔符会产生空字符串(如"a b".Split(' ')得到["a", "", "b"]) - 要用
StringSplitOptions.RemoveEmptyEntries才能过滤掉空项 - 用字符串分隔(如
str.Split(new string[] { "and", "or" }, StringSplitOptions.None))时,匹配优先级按数组顺序来:先找"and",再找"or";"xandyor"会被切成["x", "yor"],不是["x", "y", ""] - 注意:分隔符本身不能为
null或空字符串,否则抛ArgumentException
拼接多段字符串时 StringBuilder 不是“可选”,是刚需
循环内用 += 拼接 1000 次,实际创建了 1000 个临时 string 对象;GC 压力大、内存占用高、性能掉得明显。
- 只要拼接发生在循环里、或拼接次数不确定(比如日志聚合、HTML 生成),无条件用
StringBuilder - 初始化时尽量预估容量:
new StringBuilder(2048)比无参构造少一次扩容拷贝 - 别在
StringBuilder上调.ToString()太勤——每次调用都分配新字符串;攒够了再转 - 注意:
StringBuilder是可变的,但它的ToString()返回值仍是不可变字符串,后续修改不影响已生成的副本
最常被忽略的一点:所有这些方法(Substring、Replace、Split、Trim……)返回的都是新字符串,原变量值不变。如果你忘了赋值,比如写成 str.Substring(0, 5); 而没接回 str = ...,那什么都没发生。











