目录
一、字符串基础与不可变性
1.1 字符串的本质
在C#中,字符串(System.String
)是Unicode字符的不可变序列。字符串的不可变性意味着一旦创建,其内容就不能更改。任何看似修改字符串的操作实际上都会创建一个新的字符串对象。
string str1 = "Hello";
string str2 = str1; // str2和str1引用同一个对象
str1 += " World"; // 创建新对象,str1引用新对象,str2仍引用原对象
Console.WriteLine(str1); // 输出: Hello World
Console.WriteLine(str2); // 输出: Hello
1.2 字符串的内存布局
字符串在内存中的布局如下表所示:
内存区域 | 存储内容 | 大小 |
---|---|---|
对象头 | 同步块索引和类型指针 | 8字节(32位)或16字节(64位) |
长度字段 | 字符串字符数 | 4字节 |
字符数据 | 实际的Unicode字符 | 每个字符2字节 |
二、字符串拼接技术对比
2.1 常见字符串拼接方法
C#提供了多种字符串拼接方式,各有优缺点:
// 1. 使用+运算符
string result1 = "Hello" + " " + "World";
// 2. String.Concat
string result2 = string.Concat("Hello", " ", "World");
// 3. String.Format
string result3 = string.Format("{0} {1}", "Hello", "World");
// 4. 字符串插值(C# 6.0+)
string result4 = $"{
"Hello"} {
"World"}";
// 5. StringBuilder
var sb = new StringBuilder();
sb.Append("Hello");
sb.Append(" ");
sb.Append("World");
string result5 = sb.ToString();
// 6. String.Join
string[] words = {
"Hello", "World" };
string result6 = string.Join(" ", words);
2.2 性能对比测试
我们对不同拼接方法进行性能测试(拼接10000次"Hello"):
方法 | 执行时间(ms) | 内存分配(MB) | 适用场景 |
---|---|---|---|
+运算符 | 15.2 | 2.4 | 少量固定字符串拼接 |
String.Concat | 14.8 | 2.4 | 已知数量的字符串拼接 |
String.Format | 18.6 | 2.5 | 需要格式化的拼接 |
字符串插值 | 16.3 | 2.4 | C#6+代码,可读性高 |
StringBuilder | 3.7 | 0.2 | 大量或循环拼接 |
String.Join | 4.1 | 0.3 | 集合元素拼接 |
测试代码示例:
const int iterations = 10000;
var sw = new Stopwatch();
// +运算符测试
sw.Start();
string result = "";
for (int i = 0; i < iterations; i++)
{
result += "Hello";
}
sw.Stop();
Console.WriteLine($"'+' operator: {
sw.ElapsedMilliseconds}ms");
// StringBuilder测试
sw.Restart();
var sb = new StringBuilder();
for (int i = 0; i < iterations; i++)
{
sb.Append("Hello");
}
string sbResult = sb.ToString();
sw.Stop();
Console.WriteLine($"StringBuilder: {
sw.ElapsedMilliseconds}ms");
三、字符串格式化高级技巧
3.1 标准数字格式字符串
C#提供了一系列标准数字格式字符串:
double value = 12345.6789;
Console.WriteLine(value.ToString("C")); // 货币: ¥12,345.68
Console.