使用 Visual C# 提高字符串串联性能

本文介绍如何改进 Visual C# 中的字符串串联性能。

原始产品版本: Visual C#
原始 KB 数: 306822

总结

本文介绍将类用于传统串联技术的好处 StringBuilder 。 Microsoft .NET Framework 中的字符串是固定的(即,引用的文本在初始分配后为只读)。 它提供了许多性能优势,并给习惯于 C/C++ 字符串操作技术的开发人员带来了一些挑战。

本文介绍 .NET Framework 类库命名空间 System.Text

.NET Framework 中的字符串说明

改进 Visual C/C++ 中的字符串串联 strcat() 的一种方法是将大型字符数组分配为缓冲区并将字符串数据复制到缓冲区中。 在 .NET Framework 中,字符串是不可变的,无法就地修改它。 C# + 串联运算符生成一个新字符串,并在连接大量文本时导致性能降低。

但是,.NET Framework 包含一个 StringBuilder 针对字符串串联进行优化的类。 它提供与在 C/C++ 中使用字符数组相同的优势,并自动增大缓冲区大小(如果需要),并跟踪长度。 本文中的示例应用程序演示了类的使用 StringBuilder ,并将性能与串联进行比较。

生成并运行演示应用程序

  1. 启动 Visual Studio,然后创建新的 Visual C# 控制台应用程序。

  2. 以下代码使用 += 串联运算符和 StringBuilder 类对每个连接 30 个字符的 5,000 个串联时间。 将此代码添加到主过程。

    const int sLen = 30, Loops = 5000;
    int i;
    string sSource = new String('X', sLen);
    string sDest = "";
    
    // Time string concatenation.
    var stopwatch = System.Diagnostics.Stopwatch.StartNew();
    for (i = 0; i < Loops; i++) sDest += sSource;
    stopwatch.Stop();
    Console.WriteLine($"Concatenation took {stopwatch.ElapsedMilliseconds} ms.");
    
    // Time StringBuilder.
    stopwatch.Restart();
    System.Text.StringBuilder sb = new System.Text.StringBuilder((int)(sLen * Loops * 1.1));
    for (i = 0; i < Loops; i++) 
        sb.Append(sSource);
    sDest = sb.ToString();
    stopwatch.Stop();
    Console.WriteLine($"String Builder took {stopwatch.ElapsedMilliseconds} ms.");
    
    // Make the console window stay open
    // so that you can see the results when running from the IDE.
    Console.WriteLine();
    Console.Write("Press Enter to finish ... ");
    Console.Read();
    
  3. 保存应用程序。 按 F5 进行编译,然后运行应用程序。 控制台窗口应显示类似于示例的输出:

    Concatenation took 348 ms.
    String Builder took 0 ms.
    Press ENTER to finish...
    
  4. 按 Enter 停止运行应用程序并关闭控制台窗口。

故障排除

  • 如果你在支持流式处理数据的环境中(例如,在 ASPX Web 窗体或应用程序中将数据写入磁盘),请考虑避免串联或串联的 StringBuilder缓冲区开销,并通过相关流的方法或相应方法将数据直接 Response.Write 写入流。

  • 尝试在每次需要一次时重复使用现有资源 StringBuilder class ,而不是重新分配。 这会限制堆的增长并减少垃圾回收。 在任一情况下,使用 StringBuilder 类比使用 + 运算符更高效地使用堆。

参考

StringBuilder 类包含用于就地字符串操作的许多其他方法,本文未介绍这些方法。 有关详细信息,请在联机帮助中搜索 StringBuilder