C# 字符串生成器是 Dot Net 框架引入的一个概念,旨在解决字符串数据类型的性能问题。我们已经知道,字符串是一种引用类型数据类型,即其变量的内存分配在堆内存中。并且字符串一旦创建就是不可变的,即不能更改。然而,字符串生成器是可变的。
让我们看一个 C# 字符串生成器的示例,以了解其区别。假设
string str = "Hello";
对于上述变量值,将在堆内存中分配 5 字节。接下来,
str = str + “World”;
由于 C# 字符串生成器是不可变的,“World”不会与原始 str 值连接。
相反,将通过将“World”附加到“Hello”来在内存中创建另一个字符串。
堆内存
| Hello Hello World Hello World ABC . . |
这样,如果我们尝试修改 100 次,堆中将保留 100 个副本,以及一个原始字符串的副本。总共将保留 101 个副本。
C# 字符串生成器
字符串生成器是可变的,这意味着可以对字符串进行更改。并且 StringBuilder 可从 System.Text 命名空间中获取。
C# 字符串生成器语法如下所示。
StringBulder sb = new StringBuilder(“string str”); // It creates a stringbuilder with the specified string
例如
StringBulder sb = new StringBuilder(“Hello”);
这里 sb 是一个 StringBuilder 对象,它首先分配 16 字节。在修改文本时,它会根据需要将大小加倍。
如果我们知道修改文本需要多少内存的确切大小,那么我们可以将该大小作为参数传递给 C# StringBuilder。
C# 字符串生成器的语法是
StringBuilder sb = new StringBuilder(int length); // It creates an empty stringbuilder with the specified capacity as length
例如
StringBuilder sb = new StringBuilder(1000);
例如,“Hello”占用 5 字节,StringBuilder 分配 16 字节,其中剩余的 11 字节用于将来修改 C# 字符串。
假设“Hello”与另一个“World”连接,即:
sb.Append("World");
如你所知,“Hello World”总共占用了 11 字节,剩下 5 字节为空。
现在一些 ABCDEF 附加到 str
str+=ABCDEF;
Hello World, ABCDEF 需要 18 字节,但只有 16 字节可用。因此,它将内存大小加倍,即增加到 32 字节。
堆内存
Hello World ABCDEF
无论对该变量值进行了多少次更改,字符串生成器在堆内存中只维护一个副本。
注意:如果需要进行三到四次修改,则选择 String 类。如果需要对字符串进行大量更改,则选择 StringBuilder 类。
以下方法对于修改 C# 字符串生成器很有用
| 方法名称 | 描述 |
|---|---|
| StringBuilder.Append() | 在当前 StringBuilder 的末尾添加数据 |
| StringBuilder.Insert() | 在指定索引处向 StringBuilder 插入字符串。 |
| StringBuilder.Remove() | 从 StringBuilder 中移除指定数量的字符 |
| StringBuilder.Replace() | 替换指定索引处的指定字符 |
| StringBuilder.AppendFormat() | 字符串中传递的格式说明符将替换为格式化文本 |
C# 字符串生成器示例
让我们看一个关于 StringBuilder 的示例代码演示。
using System.Text;
class program
{
public static void Main()
{
string str = "Tutorial";
StringBuilder sb = new StringBuilder(str);
sb.Append(" Gateway");
Console.WriteLine(sb);
sb.Insert(0, "Welcome To ");
Console.WriteLine(sb);
sb.Replace("Welcome To", "Hello!! from");
Console.WriteLine(sb);
Console.ReadLine();
}
}
输出

分析
在这个 C# 字符串生成器示例中,str 是一个字符串变量,初始化为“Tutorial”。
sb 是 StringBuilder 类型的一个对象,str 将作为参数传递给它。
sb.Append(“Gateway”) 将把“Gateway”附加到“Tutorial”。
sb.Insert(0, “Welcome To”) 将把“Welcome To”插入到“Tutorial Gateway”的第 0 个位置。
sb.Replace(“Welcome To”, “Hello!! From”) 将把“Welcome To Tutorial Gateway”中的“Welcome To”替换为“Hello!! from”,并打印
“Hello !! from Tutorial Gateway”
让我们编写代码来了解 StringBuilder 类相对于 String 类的性能。
C# 字符串生成器查找差异
在这里,我们将找出 String 和 StringBuilder 在执行相同次数的迭代时所花费的时间差异。
using System;
using System.Text;
using System.Diagnostics;
class program
{
public static void Main(string[] args)
{
string s = "";
Stopwatch st = new Stopwatch();
st.Start();
for (int i = 1; i <= 5000; i++)
{
s = s + i;
}
st.Stop();
StringBuilder sb = new StringBuilder(5000);
Stopwatch st1 = new Stopwatch();
st1.Start();
for (int i=1;i<=5000;i++)
{
sb.Append(i);
}
st1.Stop();
Console.WriteLine("Time taken for string: " + st.ElapsedMilliseconds);
Console.WriteLine("Time taken for StringBuilder: " + st1.ElapsedMilliseconds);
Console.ReadLine();
}
}

分析
在这个 C# 字符串生成器示例中,我们将使用一个空的 s。接下来,我们创建了一个 StopWatch 类并为其创建了一个实例 st。此 StopWatch 类来自 System.Diagnostics 命名空间。
st.Start() 将在循环开始之前启动 StopWatch。
我们编写了 C# for 循环,其中 int i 初始化为 1,i 将迭代 5000 次。每次 i 值都与字符串变量 s 连接。
st.Stop() 将停止 StopWatch()。
同样,它还为字符串生成器创建了一个实例 sb,其中 5000 作为参数传递,这意味着 sb 创建了一个容量为 5000 的空字符串。
在循环开始之前,StopWatch 创建了它的实例,并调用了 start()。
这里循环也迭代 5000 次,每次 i 值都附加到它。迭代完成后,StopWatch 停止。
最后,我们使用 StopWatch 类的 ElapsedMilliseconds 属性分别打印了 String 和 StringBuilder 所花费的时间。
在这里,找到差异!String 进行 5000 次迭代需要 20 毫秒,而 String Builder 进行相同次数的迭代需要 1 毫秒。