一、string 基础:创建、拼接与插值
1. 字符串的创建方式
常见的创建方式有:
csharp
string s1 = "Hello"; // 字面量
string s2 = new string('a', 5); // "aaaaa"
char[] chars = { 'H', 'i' };
string s3 = new string(chars); // "Hi"
string? s4 = null; // 可空字符串引用
2. 字符串拼接
常见方式:
csharp
string a = "Hello";
string b = "World";
// 方式一:+ 拼接
string c1 = a + ", " + b;
// 方式二:string.Concat
string c2 = string.Concat(a, ", ", b);
// 方式三:string.Format
string c3 = string.Format("{0}, {1}", a, b);
// 方式四:字符串插值(C# 6+)
string c4 = $"{a}, {b}";
// 方式五:string.Join(常用于列表拼接)
string[] items = { "Apple", "Banana", "Cherry" };
string joined = string.Join(", ", items); // "Apple, Banana, Cherry"
使用建议:
- 少量字符串拼接:
+或$""插值即可,代码可读性最高。 - 多个元素拼接:
string.Join更方便。 - 大量循环拼接:使用
StringBuilder(后文详讲),避免产生大量临时字符串。
3. 字符串插值
csharp
int id = 123;
string name = "张三";
string msg = $"用户 {name} 的编号是 {id}";
高级用法:
- 指定格式:
csharp
DateTime now = DateTime.Now;
string msg = $"当前时间:{now:yyyy-MM-dd HH:mm:ss}";
- 对齐输出(用于控制台表格):
csharp
int price = 100;
string line = $"价格: {price,10} 元"; // 右对齐,占 10 宽度
string line2 = $"价格: {price,-10} 元"; // 左对齐,占 10 宽度
- 与
@$组合(多行 + 插值):
csharp
string name = "Alice";
string text = $@"Hello {name},
欢迎使用 C# 字符串插值。
这是多行文本。";
注意:
$@"..."的顺序可以是$@"..."或@$"...",效果相同。
二、字符串的不可变性与内存模型
1. 不可变性的含义
在 C# 中,string 是不可变的(immutable):
- 一旦创建,其内容就不能被修改。
- 看起来像是在"修改"字符串的操作,实际上都会返回一个新字符串。
示例:
csharp
string s = "Hello";
string t = s.ToUpper(); // s 仍然是 "Hello",t 是 "HELLO"
三、常见基础操作:长度、索引、遍历
1. 获取长度
csharp
string s = "Hello";
int len = s.Length; // 5
注意:
Length的单位是"char的个数",而不是"用户眼中的字符数"。- 对于包含某些 Unicode 组合字符、表情的字符串,
Length可能"看起来"不直观,例如:
csharp
string s = "😄";
int len = s.Length; // 可能为 2(因为 UTF-16 中用两个 char 表示一个表情)
2. 按索引访问
csharp
string s = "Hello";
char first = s[0]; // 'H'
char last = s[s.Length - 1]; // 'o'
3. 遍历字符
csharp
string s = "Hello";
foreach (char c in s)
{
Console.WriteLine(c);
}
四、字符串比较:Equals、==、Compare
1. == 与 Equals
csharp
string a = "hello";
string b = "hello";
string c = "HELLO";
bool b1 = (a == b); // True,按内容比较
bool b2 = a.Equals(b); // True
bool b3 = a.Equals(c); // False
默认情况下:
==和Equals都是"区分大小写"的比较,使用"序号比较"。
2. 指定比较规则
更推荐使用带 StringComparison 的重载,避免文化差异和大小写问题:
csharp
string a = "straße";
string b = "STRASSE";
// 区分大小写的序号比较(基于 UTF-16 编码值)
bool ord = a.Equals(b, StringComparison.Ordinal); // False
// 忽略大小写的序号比较
bool ordIgnore = a.Equals(b, StringComparison.OrdinalIgnoreCase); // True 或 False,取决于具体字符串
// 当前区域性的忽略大小写比较
bool ci = a.Equals(b, StringComparison.CurrentCultureIgnoreCase); // True
常用的 StringComparison 有:
Ordinal:执行序号比较。OrdinalIgnoreCase:忽略大小写的序号比较。CurrentCulture/CurrentCultureIgnoreCase:使用当前区域性执行区分/不区分大小写的比较。InvariantCulture/InvariantCultureIgnoreCase:使用固定区域性执行区分/不区分大小写的比较。
string.Compare
csharp
int result = string.Compare("abc", "abd", StringComparison.Ordinal);
// result < 0 :第一个小于第二个
// result == 0:相等
// result > 0 :第一个大于第二个
常用于:
- 排序自定义比较器
- 实现区间判断(例如字符串范围)
五、大小写转换与裁剪:ToUpper/Lower、Trim
1. 大小写转换
csharp
string s = "Hello World";
// 基于当前区域的转换
string upper = s.ToUpper();
string lower = s.ToLower();
// 基于不同区域的转换(常用于协议、配置)
string upperInvariant = s.ToUpperInvariant();
string lowerInvariant = s.ToLowerInvariant();
2. 删除前后空白:Trim
csharp
string s = " hello ";
string t1 = s.Trim(); // "hello"
string t2 = s.TrimStart(); // "hello "
string t3 = s.TrimEnd(); // " hello"
可以自定义要裁剪的字符:
csharp
string s = "---hello***";
string t = s.Trim('-', '*'); // "hello"
六、查找与包含判断:IndexOf、Contains、StartsWith、EndsWith
1. Contains
csharp
string s = "Hello World";
bool hasHello = s.Contains("Hello"); // true
bool has = s.Contains("hello", StringComparison.OrdinalIgnoreCase);
2. IndexOf / LastIndexOf
csharp
string s = "Hello World";
// 从头查找
int idx = s.IndexOf("World"); // 6
int idx2 = s.IndexOf("world", StringComparison.OrdinalIgnoreCase); // 6
// 从指定位置开始查找
int idx3 = s.IndexOf("l", 3); // 3 之后的第一个 'l' 的位置
int lastIdx = s.LastIndexOf("l"); // 最后一个 'l' 的位置
返回值含义:
-
= 0:找到子串起始位置
- -1:未找到
3. StartsWith / EndsWith
csharp
string s = "image.png";
bool isPng = s.EndsWith(".png", StringComparison.OrdinalIgnoreCase);
bool isHttp = s.StartsWith("http://", StringComparison.OrdinalIgnoreCase);
七、截取与分割:Substring、Split、Join
1. Substring
csharp
string s = "Hello World";
// 从 index 到结尾
string sub1 = s.Substring(6); // "World"
// 从 index 开始,长度为 length
string sub2 = s.Substring(0, 5); // "Hello"
2. Split:按分隔符拆分
csharp
string s = "apple,banana,cherry";
// 基本用法
string[] arr = s.Split(','); // ["apple", "banana", "cherry"]
// 多个分隔符
string s2 = "apple,banana;cherry";
string[] arr2 = s2.Split(new[] { ',', ';' }, StringSplitOptions.None);
// 去掉空项
string s3 = "a,,b,,c";
string[] arr3 = s3.Split(',', StringSplitOptions.RemoveEmptyEntries); // ["a","b","c"]
StringSplitOptions 有:
None:保留空字符串RemoveEmptyEntries:移除空字符串
3. Join:拼接数组/集合
csharp
string[] items = { "apple", "banana", "cherry" };
string joined = string.Join(",", items); // "apple,banana,cherry"
八、替换与移除:Replace、Remove、Insert
1. Replace
csharp
string s = "Hello World";
// 替换子串
string replaced = s.Replace("World", "C#"); // "Hello C#"
// 替换字符
string s2 = "1-2-3-4";
string r = s2.Replace('-', ':'); // "1:2:3:4"
2. Remove
csharp
string s = "Hello World";
// 从 index 删除到结尾
string r1 = s.Remove(5); // "Hello"
// 从 index 删除 count 个字符
string r2 = s.Remove(5, 1); // "HelloWorld" (删掉中间那个空格)
3. Insert
csharp
string s = "HelloWorld";
string r = s.Insert(5, " "); // "Hello World"
九、格式化输出:string.Format、插值与数值格式
1. string.Format
csharp
int count = 10;
double price = 3.5;
string msg = string.Format("你买了 {0} 个,总价 {1:C}", count, price);
// {1:C} 表示货币格式
常用占位符格式:
- 数值:
{0}、{0:N2}(带千分位,保留 2 位小数) - 货币:
{0:C} - 百分比:
{0:P} - 时间:
{0:yyyy-MM-dd HH:mm:ss}
2. 字符串插值 + 格式
基本等价于 string.Format,但更清晰:
csharp
int count = 10;
double price = 3.5;
string msg = $"你买了 {count} 个,总价 {price:C}";
十、StringBuilder:高频拼接必备
1. 常用方法
csharp
var sb = new StringBuilder();
sb.Append("Hello");
sb.Append(' ');
sb.AppendLine("World"); // 自动加 \r\n
sb.Insert(0, "==> "); // 在开头插入
sb.Replace("World", "C#");
sb.Remove(0, 4); // 删除前 4 个字符
string final = sb.ToString();
2. 初始化容量
如果能预估最终长度,可提前设置容量,减少扩容次数:
csharp
var sb = new StringBuilder(capacity: 1024);
十一、字符串与编码:UTF-16、UTF-8 与 byte[] 互转
1. 字符串与字节数组互转
使用 System.Text.Encoding:
csharp
using System.Text;
string s = "你好,世界";
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
// 字符串 -> byte[]
byte[] utf8Bytes = Encoding.UTF8.GetBytes(s);
byte[] asciiBytes = Encoding.GetEncoding("gbk").GetBytes(s);
// byte[] -> 字符串
string sFromUtf8 = Encoding.UTF8.GetString(utf8Bytes);
string sFromGb = Encoding.GetEncoding("gbk").GetString(asciiBytes);
2. 常见编码类型
Encoding 提供的常用编码:
Encoding.UTF8Encoding.Unicode(UTF-16 little-endian)Encoding.BigEndianUnicodeEncoding.ASCIIEncoding.GetEncoding("GB2312")/"GBK"/"GB18030"等(需要平台支持)
结语
点个赞,关注我获取更多实用 C# 技术干货!如果觉得有用,记得收藏本文