前言
在C#编程中字符串拼接是一种常见且基础的操作,广泛应用于各种场景,如动态生成SQL查询、构建日志信息、格式化用户显示内容等。然而,不同的字符串拼接方式在性能和内存使用上可能存在显著差异。今天咱们一起来看看在C#中字符串拼接的常见6种方式及其使用BenchmarkDotNet
进行性能分析对比。
BenchmarkDotNet
BenchmarkDotNet是一个基于.NET开源、功能全面、易于使用的性能基准测试框架,它为.NET开发者提供了强大的性能评估和优化能力。通过自动化测试、多平台支持、高级统计分析和自定义配置等特性,BenchmarkDotNet帮助开发者更好地理解和优化软件系统的性能表现。
拼接基础数据
` private const int IterationCount = 1000;`
` private const string StringPart1 = "追逐时光者";`
` private const string StringPart2 = "DotNetGuide";`
` private const string StringPart3 = "DotNetGuide技术社区";`
` private readonly string[] _stringPartsArray = { "追逐时光者", "DotNetGuide", "DotNetGuide技术社区" };`
+
操作符
` /// <summary>`
` /// 使用 + 操作符拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string PlusOperator()`
` {`
` string result = StringPart1 + " " + StringPart2 + " " + StringPart3;`
` return result;`
` }`
$
内插字符串
` /// <summary>`
` /// 使用 $ 内插字符串拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string InterpolatedString()`
` {`
` string result = $"{StringPart1} {StringPart2} {StringPart3}";`
` return result;`
` }`
String.Format
` /// <summary>`
` /// 使用string.Format()拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringFormat()`
` {`
` string result = string.Format("{0} {1} {2}", StringPart1, StringPart2, StringPart3);`
` return result;`
` }`
String.Concat
` /// <summary>`
` /// 使用string.Concat()拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringConcat()`
` {`
` string result = string.Concat(StringPart1, " ", StringPart2, " ", StringPart3);`
` return result;`
` }`
String.Join
` /// <summary>`
` /// 使用string.Join()拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringJoin()`
` {`
` string result = string.Join(" ", _stringPartsArray);`
` return result;`
` }`
StringBuilder
Append拼接字符串
` /// <summary>`
` /// 使用StringBuilder.Append拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringBuilderAppend()`
` {`
` StringBuilder stringBuilder = new StringBuilder();`
` stringBuilder.Append(StringPart1);`
` stringBuilder.Append(" ");`
` stringBuilder.Append(StringPart2);`
` stringBuilder.Append(" ");`
` stringBuilder.Append(StringPart3);`
` return stringBuilder.ToString();`
` }`
AppendFormat拼接字符串
` /// <summary>`
` /// 使用StringBuilder.AppendFormat拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringBuilderAppendFormat()`
` {`
` StringBuilder stringBuilder = new StringBuilder();`
` stringBuilder.AppendFormat("{0} {1} {2}", StringPart1, StringPart2, StringPart3);`
` return stringBuilder.ToString();`
` }`
性能基准对比测试完整代码
咱们分别以少量字符串拼接和大量字符串拼接为例,进行性能基准对比测试:
说明:
- Mean: 所有测量值的算术平均值。
- Error: 99.9% 置信区间的一半。
- StdDev: 所有测量值的标准差。
- Gen0: 第 0 代 GC 每 1000 次操作收集一次。
- Gen1: 第 1 代 GC 每 1000 次操作收集一次。
- Gen2: 第 2 代 GC 每 1000 次操作收集一次。
- Allocated: 每次操作分配的内存(仅托管内存,包含所有内容,1KB = 1024B)。
- 1 ms: 1 毫秒(0.001 秒)。
少量字符串拼接
` using BenchmarkDotNet.Attributes;`
`using System.Text;`
`namespace BenchmarkDotNetExercise`
`{`
` [MemoryDiagnoser]//记录内存分配情况`
` public class StringConcatenationBenchmark`
` {`
` private const int IterationCount = 1000;`
` private const string StringPart1 = "追逐时光者";`
` private const string StringPart2 = "DotNetGuide";`
` private const string StringPart3 = "DotNetGuide技术社区";`
` private readonly string[] _stringPartsArray = { "追逐时光者", "DotNetGuide", "DotNetGuide技术社区" };`
` #region 少量字符串拼接`
` /// <summary>`
` /// 使用 + 操作符拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string PlusOperator()`
` {`
` string result = StringPart1 + " " + StringPart2 + " " + StringPart3;`
` return result;`
` }`
` /// <summary>`
` /// 使用 $ 内插字符串拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string InterpolatedString()`
` {`
` string result = $"{StringPart1} {StringPart2} {StringPart3}";`
` return result;`
` }`
` /// <summary>`
` /// 使用string.Format()拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringFormat()`
` {`
` string result = string.Format("{0} {1} {2}", StringPart1, StringPart2, StringPart3);`
` return result;`
` }`
` /// <summary>`
` /// 使用string.Concat()拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringConcat()`
` {`
` string result = string.Concat(StringPart1, " ", StringPart2, " ", StringPart3);`
` return result;`
` }`
` /// <summary>`
` /// 使用string.Join()拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringJoin()`
` {`
` string result = string.Join(" ", _stringPartsArray);`
` return result;`
` }`
` /// <summary>`
` /// 使用StringBuilder.Append拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringBuilderAppend()`
` {`
` StringBuilder stringBuilder = new StringBuilder();`
` stringBuilder.Append(StringPart1);`
` stringBuilder.Append(" ");`
` stringBuilder.Append(StringPart2);`
` stringBuilder.Append(" ");`
` stringBuilder.Append(StringPart3);`
` return stringBuilder.ToString();`
` }`
` /// <summary>`
` /// 使用StringBuilder.AppendFormat拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string StringBuilderAppendFormat()`
` {`
` StringBuilder stringBuilder = new StringBuilder();`
` stringBuilder.AppendFormat("{0} {1} {2}", StringPart1, StringPart2, StringPart3);`
` return stringBuilder.ToString();`
` }`
` #endregion`
` }`
`}`
![](https://img2024.cnblogs.com/blog/1336199/202502/1336199-20250213203735413-1648428090.png)
大量字符串拼接
` using BenchmarkDotNet.Attributes;`
`using System.Text;`
`namespace BenchmarkDotNetExercise`
`{`
` [MemoryDiagnoser]//记录内存分配情况`
` public class StringConcatenationBenchmark`
` {`
` private const int IterationCount = 1000;`
` private const string StringPart1 = "追逐时光者";`
` private const string StringPart2 = "DotNetGuide";`
` private const string StringPart3 = "DotNetGuide技术社区";`
` private readonly string[] _stringPartsArray = { "追逐时光者", "DotNetGuide", "DotNetGuide技术社区" };`
` #region 大量字符串拼接`
` /// <summary>`
` /// 使用 + 操作符拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string BigDataPlusOperator()`
` {`
` string result = string.Empty;`
` for (int i = 0; i < IterationCount; i++)`
` {`
` result += StringPart1 + " " + StringPart2 + " " + StringPart3;`
` }`
` return result;`
` }`
` /// <summary>`
` /// 使用StringBuilder.Append拼接字符串`
` /// </summary>`
` /// <returns></returns>`
` [Benchmark]`
` public string BigDataStringBuilderAppend()`
` {`
` StringBuilder stringBuilder = new StringBuilder();`
` for (int i = 0; i < IterationCount; i++)`
` {`
` stringBuilder.Append(StringPart1);`
` stringBuilder.Append(" ");`
` stringBuilder.Append(StringPart2);`
` stringBuilder.Append(" ");`
` stringBuilder.Append(StringPart3);`
` }`
` return stringBuilder.ToString();`
` }`
` #endregion`
` }`
`}`
![](https://img2024.cnblogs.com/blog/1336199/202502/1336199-20250213203758070-346458999.png)