字符串

Char 类相似,System.String 类也提供了大量的静态方法。由于字符串是不可变的(Immutable),这些静态方法通常用于合并、拆分、查找、格式化以及处理空值检查

创建字符

(1) 最简单方法就是将字面量赋给一个变量
string s = @"\\server\share\folder\file.txt";

(2) 使用 string 类的构造器,创建一个重复的字符序列
string sep=new string('=',30);

(3) 用char数组来构造一个字符串

string charToString = new string(chars); ```

## 访问字符串中的字符
字符串的索引器可以返回一个指定索引位置的字符。和所有操作字符串的方法相似,索引是从0开始计数的string 还实现了 IEnumerable<char> ,所以可以用 foreach 遍历它的字符。

```csharp
  string s = "This is a sample string.";
  Console.WriteLine(s);
  Console.WriteLine($"第1个字母:{s[0]}");//T

  foreach (char c in s)
  {
    //Console.WriteLine(c);
    Console.WriteLine($"字符:{c}  - ASCII值: {((short)c).ToString().PadLeft(3,' ')} - 十六进制: {((short)c).ToString("X2")} ");
  }

String 类常用的静态方法汇总

1. 判空与校验 (常用)

这些方法是 C# 开发中最常用于防御性编程的手段。

方法名称 代码示例 功能解释
IsNullOrEmpty string.IsNullOrEmpty(s) 检查字符串是否为 null空字符串 (“”)
IsWhiteSpace string.IsNullOrWhiteSpace(s) 检查是否为 null、空字符串或仅由空白字符组成

空字符串指长度为零的字符串。我们可以使用字面量或静态 string.Empty 字段来创建一个空字符串

  • 空字符串
    string s1 = "";
    Console.WriteLine(s1=="");
    Console.WriteLine( s1==string.Empty);
    Console.WriteLine(s1.Length==0?"Empty":$"{s1.Length}");

  • null
    字符串是引用类型,因此它可以为null
    string s2 = null;
    Console.WriteLine(s2==null);
    Console.WriteLine(s2==string.Empty);
    //Console.WriteLine(s2.Length==0?"Empty":$"{s2.Length}");//报错
    Console.WriteLine(string.IsNullOrEmpty(s2));

2.字符串内搜索

方法名称 代码示例 功能解释
StartsWith "HelloWorld".StartsWith("Hello") 判断字符串是否以指定字符串开头,返回 true / false
EndsWith "HelloWorld".EndsWith("World") 判断字符串是否以指定字符串结尾,返回 true / false
Contains "HelloWorld".Contains("loWo") 判断字符串中是否包含指定子串
IndexOf "HelloWorld".IndexOf("o") 返回第一次出现的位置索引,找不到返回 -1
LastIndexOf "HelloWorld".LastIndexOf("o") 返回最后一次出现的位置索引
IndexOfAny "abc123".IndexOfAny(new[] { '1','2','3' }) 返回任意字符首次出现的位置
LastIndexOfAny "abc123".LastIndexOfAny(new[] { '1','2','3' }) 返回任意字符最后出现的位置
  • 1️⃣ 忽略大小写的写法
    StartsWith 和 EndsWith 提供了重载方法,使用 StringComparison 枚举或者 CultureInfo 对象来控制大小写和文化相关的规则。 其默认行为是使用当前文化规则执行区分大小写的匹配。使用了不变文化规则执行不区分大小写的搜索。
"HelloWorld".StartsWith("hello", StringComparison.OrdinalIgnoreCase);

string s = "This is a sample string.";
var r = s.StartsWith("this", StringComparison.InvariantCultureIgnoreCase);
Console.WriteLine($"以this开头:{r}");

r = s.EndsWith(".", StringComparison.InvariantCultureIgnoreCase);
Console.WriteLine($"以点结尾:{r}");

r = s.Contains("sample", StringComparison.InvariantCultureIgnoreCase);
Console.WriteLine($"包含单词sample:{r}");

  • 2️⃣ IndexOf 常见判断方式
    IndexOf 的功能更强,它返回指定字符或者字符串的首次出现的位置( -1 则表示该子字符串不存在),IndexOf 也提供了重载方法,不但接受 StringComparison 枚举值,还可以接受startPosition 参数,指定初始搜索的索引位置,LastIndexOf 和 IndexOf 类似,只是它是从后向前进行搜索的。IndexOfAny 返回字符串中和给定字符集合中的任意一个字符相匹配的第一个位置, LastIndexOfAny 则从相反方向执行相同操作。
if (text.IndexOf("abc") >= 0)
{
    // 找到了
}

string s = "This is a sample string.";
Console.WriteLine(s);
int index1 = s.IndexOf('s');
Console.WriteLine($"第1个s的位置:{index1}");//3


int index2 = s.IndexOf("is");//返回指定字符或者字符串的首次出现的位置( -1 则表示该子字符串不存在)
Console.WriteLine($"第1个is的位置:{index2}");//2

//重载方法,不但接受 StringComparison 枚举值,还可以接受 startPosition 参数,指定初始搜索的索引位置
int index2b = s.IndexOf("is", 3);
Console.WriteLine($"从索引3开始,第1个is的位置:{index2b}");//5

//IndexOfAny 返回字符串中和给定字符集合中的任意一个字符相匹配的第一个位置
int index2c = s.IndexOfAny(new char[] { 'a', 'e', 'i', 'o', 'u' });
Console.WriteLine($"第1个元音字母的位置:{index2c}");//2

int index3 = s.LastIndexOf('s'); //从后向前进行搜索的
Console.WriteLine($"最后1个s的位置:{index3}");//15

int index4 = s.LastIndexOf("is");
Console.WriteLine($"最后1个is的位置:{index4}");//5    

//LastIndexOfAny 则从相反方向执行相同操作
int index4b = s.LastIndexOfAny(new char[] { 'a', 'e', 'i', 'o', 'u' });
Console.WriteLine($"最后1个元音字母的位置:{index4b}");//17
  • 3️⃣ 典型应用场景速记
  • StartsWith / EndsWith
    👉 文件名、协议头、路径后缀判断
  • Contains
    👉 关键词搜索、模糊匹配
  • IndexOf / LastIndexOf
    👉 截取字符串、解析协议
  • IndexOfAny
    👉 查找第一个分隔符, ; | 等)

3.字符串处理

string 是不可变的,因此所有“处理”字符串的方法都会返回一个新的字符串,而原始的字符串则不受影响(其效果和重新为一个字符串变量赋值一样)

Substring 方法可以提取部分字符串,若省略长度,则会得到剩余的字符串。

Insert 和 Remove 在特定的位置插入或者删除一些字符

PadLeft 和 PadRight 会用特定的字符(如果未指定则使用空格)将字符串填充为指定的长度.如果输入字符串长度大于填充长度,则返回不发生变化的原始字符串。

TrimStart 和 TrimEnd 会从字符串的开始或结尾删除指定的字符, Trim 则是从开始和结尾执行删除操作。这些方法默认会删除空白字符(包括空格、制表符、换行和这些字符的Unicode变体)。

Replace 会替换字符串中所有(非重叠的)特定字符或子字符串

ToUpper 和 ToLower 会返回与输入字符串相对应的大写和小写字符串。默认情况下,它会受用户当前语言设置的影响, ToUpperInvariant 和 ToLowerInvariant 则总是应用英语字母表规则。


方法名称 代码示例 功能解释
Substring "HelloWorld".Substring(5) 从指定索引开始截取子字符串
Insert "HelloWorld".Insert(5, " ") 在指定索引位置插入字符串
Remove "HelloWorld".Remove(5, 5) 从指定索引开始删除指定长度字符
PadLeft "123".PadLeft(5, '0') 字符串左侧补齐到指定长度
PadRight "123".PadRight(5, '0') 字符串右侧补齐到指定长度
TrimStart " Hello ".TrimStart() 移除字符串开头的空白字符
TrimEnd " Hello ".TrimEnd() 移除字符串结尾的空白字符
Trim " Hello ".Trim() 移除字符串两端的空白字符
Replace "A-B-C".Replace("-", "_") 将字符串中的指定内容替换
ToUpper "hello".ToUpper() 将字符串转换为大写
ToLower "HELLO".ToLower() 将字符串转换为小写

  • 1️⃣ Substring 防越界写法
string s = "Hello";
string part = s.Length >= 3 ? s.Substring(0, 3) : s;
  • 2️⃣ Trim 指定字符
"***Hello***".Trim('*');     // "Hello"
"000123000".Trim('0');      // "123"
  • 3️⃣ PadLeft 的典型应用
int id = 25;
string code = id.ToString().PadLeft(6, '0'); // 000025
  • 4️⃣ Replace + 链式处理
string clean = text
    .Trim()
    .Replace("\r\n", " ")
    .ToUpper();

  • 截取Substring
  • 插删Insert / Remove
  • 补齐PadLeft / PadRight
  • 清洗Trim* / Replace
  • 规范化ToUpper / ToLower

4. 合并与拆分

Split 将字符串分割为若干部分: 默认情况下, Split 使用空白字符作为分隔符,重载的方法也可以接收 char 和 string 分隔符的 params 数组。Split 还可以接受一个 StringSplitOptions 枚举值以删除空项。这在一行文本中有多种单词分隔符时很有用。

静态方法 Join 则执行和 Split 相反的操作。它需要一个分隔符和字符串的数组。
静态方法 Concat 和 Join 类似,但是它仅仅接受一个字符串的 params 数组,且不支持分隔符。Concat 操作和 + 操作符效果完全相同(实际上,编译器会将 + 转换为 Concat )

用于处理多个字符串或集合之间的转换。

方法名称 代码示例 功能解释
Join string.Join(",", arr) 将数组/集合中的元素用分隔符连接成一个字符串。
Concat string.Concat("A", "B", "C") 将多个对象或字符串直接连接在一起。
string s="This is a sample string.  ";
string[] words = s.Split();
foreach (var w in words)
{
    Console.Write($"{w} | ");
}

string[] words = s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

string together = string.Join('-',words);
Console.WriteLine(together);

5. 比较

.NET在两个值的比较上划分了两个不同的概念:相等比较(equality comparison)和顺序比较(order comparison)。相等比较验证两个实例是否从语义上是相同的,而顺序比较则验证两个实例(如果有的话)按照升序或者降序排列的话,哪一个应当首先出现。

字符串之间可以使用 ==操作符或者 string 的 Equals 方法来进行相等比较。后者可以指定一些选项(例如,不区分大小写),因此功能更强。 如果将变量转换为 object 类型,则 == 就不一定是按字符串处理的了字符串的顺序比较则可使用实例方法 CompareTo 或者静态方法 Compare 或CompareOrdinal ,这些方法会返回一个正数、负数或者0。这取决于第一个值是在第二个值之后、之前还是同时出现。


  1. 序列比较与文化相关的字符串比较
    字符串比较有两种基本算法,序列比较(ordinal)和文化相关的比较(culture-sensitive)。序列比较会直接将字符串解析为数字(按照它们的Unicode字符数值),而文化相关的比较则参照特定的字母表来解析字符。有两种特殊的文化:“当前文化”(current culture),基于计算机控制面板的设定;“不变文化”(invariant culture),在任何计算机上都是相同的(并且和美国文化密切一致)。 对于相等比较,序列和文化相关的算法都是非常有用的。而排序时,人们则通常选择文化相关的比较,这是因为当按照字符进行排序时,通常需要一个字母顺序表。序列比较依赖的是Unicode的数字位置,这恰好会使英文字母按照顺序排列,但即使是这样也可能不能满足要求ode的数字位置,这恰好会使英文字母按照顺序排列,但即使是这样也可能不能满足要求
  1. 字符串的相等比较
    尽管序列比较有其局限性,但是字符串的 == 运算符总是执行区分大小写的序列比较。不带有参数的 string.Equals 方法也是用同样的方式。这就是 string 类型的“默认”相等比较的行为。 字符串的 == 和 Equals 方法选择序列算法的原因是它既高效又确定。字符串相等比较是基础操作,并远比顺序比较使用频繁。“严格”的相等概念与 == 运算符的一般用途是一致的
  1. 字符串的顺序比较
    String 的实例方法 CompareTo 执行文化相关的区分大小写的顺序比较。与 == 运算符不同,CompareTo 不使用序列比较。这是因为对于排序来说,文化相关的算法更为有效。
    实例方法 CompareTo 实现了 IComparable 泛型接口,它也是在整个.NET库中使用的标准比较协议。
    这意味着 string 的 CompareTo 定义了字符串在应用程序中,作为集合元素时排序的默认行为。关于 IComparable 的更多内容,对于其他类型的比较则可以调用静态方法 Compare 和 CompareOrdinal
    所有的顺序比较方法都返回正数、负数或者零,这取决于第一个值是在第二个值之后、之前还是相同的位置

用于处理不同文化或规则下的字符串比对。

方法名称 代码示例 功能解释
Compare string.Compare(s1, s2, true) 比较两个字符串(第三个参数可设置是否忽略大小写)。返回整数。
Equals string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase) 静态判断两个字符串是否相等,可指定特殊的比较规则

6. 格式化与填充

用于生成动态内容或对齐文本。
String.Format:供了创建嵌入变量的字符串的便利方法。嵌入的变量(或值)可以是任何类型,而 Format 则会直接调用它们的 ToString 方法。 包含嵌入变量的主字符串称为组合格式字符串。调用 String.Format 时,需要提供一个组合格式字符串,后面紧跟每一个嵌入的变量。
花括号里面的每一个数字称为格式项(format item),这些数字对应参数的位置,后面可以跟随:
· 逗号与应用的最小宽度(minimum width)。
· 冒号与格式字符串(format string)。
最小宽度用于对齐各个列。如果其值为负数,则为左对齐,否则为右对齐。

方法名称 代码示例 功能解释
Format string.Format("Id: {0}", id) 使用占位符将变量插入模板字符串(C# 6.0 后常用 $ 插值代替)。

string s1 = string.Format("{0}+{1}={2}", 1, 2, 1 + 2);
Console.WriteLine(s1);

string s2 = $"{1}+{2}={1 + 2}";
Console.WriteLine(s2);

7. 内存与性能优化 (高级)

处理字符串驻留池或特定字符集。

方法名称 代码示例 功能解释
Intern string.Intern(s) 检查系统是否已在驻留池中记录了该字符串,并返回引用以节省内存。
IsInterned string.IsInterned(s) 检查字符串是否已经在驻留池中。

静态方法 vs 实例方法

常会混淆这两者。请看对比:

  • 静态方法:通过类名调用,通常用于“从无到有”或“多对一”。

  • string.Join(...)(把一堆变一个)

  • string.IsNullOrEmpty(s)(即便 s 是 null 也不会报错)

  • 实例方法:通过变量名调用,通常用于“改变自身”。

  • s.Trim()

  • s.Replace("a", "b")

  • s.Substring(0, 5)

特别注意:调用 s.ToUpper() 时,如果 snull,程序会崩溃(NullReferenceException)。而使用静态方法 string.IsNullOrEmpty(s) 则是安全的。

几个在日常开发(尤其是处理路径操作)中非常实用代码示例

1. 字符串校验与格式化

这是处理用户输入或配置文件路径时的标准写法。

string inputPath = "  C:\\Users\\Test\\Data  ";

// 1. 安全校验:防止 Null 或全是空格导致的崩溃
if (!string.IsNullOrWhiteSpace(inputPath))
{
    // 2. 实例方法:修剪空格
    string cleanedPath = inputPath.Trim();

    // 3. 静态方法:格式化输出
    string message = string.Format("正在处理路径: {0},时间: {1:yyyy-MM-dd}", 
                                    cleanedPath, DateTime.Now);
    Console.WriteLine(message);
}


2. 数组合并(String.Join)

假设你从某个列表或数据库中获取了一组文件名,需要拼成一条命令或显示在 UI 上。

string[] files = { "Micro-A01.lbl", "ZENNER-Dev.lbl", "Temp.txt" };

// 静态方法:用分号和空格连接数组元素
string fileList = string.Join("; ", files);

Console.WriteLine("待处理文件: " + fileList);
// 输出: 待处理文件: Micro-A01.lbl; ZENNER-Dev.lbl; Temp.txt


3. 高级比较(String.Equals)

在处理路径或文件名时,Windows 通常不区分大小写,这时使用静态的 Equals== 更安全且意图明确。

string fileName = "Micro-M00-A01.lbl";
string targetName = "micro-m00-a01.LBL";

// 静态方法:指定忽略大小写进行比对
bool isSameFile = string.Equals(fileName, targetName, StringComparison.OrdinalIgnoreCase);

if (isSameFile)
{
    Console.WriteLine("文件名匹配(忽略大小写)");
}


4. 字符串与 Char 的联动:字符过滤

结合 String 的构造函数和 Char 的静态方法,可以快速清洗字符串(例如从你的 JSON 输出中提取数字)。

string rawData = "Exit Code: 0, Status: OK";

// 提取所有数字:利用 LINQ 配合 Char.IsDigit
char[] digits = rawData.Where(c => char.IsDigit(c)).ToArray();
string codeOnly = new string(digits);

Console.WriteLine("提取到的数字为: " + codeOnly); // 输出: 0


总结

如何选择?

  • 检查状态:用 string.IsNullOrEmptystring.IsNullOrWhiteSpace
  • 拼凑内容:用 string.Joinstring.Format
  • 逻辑判断:用 string.Equals
  • 单个字符处理:交给 char.Is... 系列。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐