C#字符串拼接的几种方式及其性能分析对比
前言
在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 = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += StringPart1 + " " + StringPart2 + " " + StringPart3;
}
return result;
}
$内插字符串
/// <summary>
/// 使用 $ 内插字符串拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string InterpolatedString()
{
string result = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += $"{StringPart1} {StringPart2} {StringPart3}";
}
return result;
}
String.Format
/// <summary>
/// 使用string.Format()拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string StringFormat()
{
string result = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
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.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += string.Concat(StringPart1, " ", StringPart2, " ", StringPart3);
}
return result;
}
String.Join
/// <summary>
/// 使用string.Join()拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string StringJoin()
{
string result = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += string.Join(" ", _stringPartsArray);
}
return result;
}
StringBuilder
/// <summary>
/// 使用StringBuilder拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string StringBuilder()
{
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();
}
性能基准对比测试完整代码
[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技术社区" };
/// <summary>
/// 使用 + 操作符拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string PlusOperator()
{
string result = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += StringPart1 + " " + StringPart2 + " " + StringPart3;
}
return result;
}
/// <summary>
/// 使用 $ 内插字符串拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string InterpolatedString()
{
string result = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += $"{StringPart1} {StringPart2} {StringPart3}";
}
return result;
}
/// <summary>
/// 使用string.Format()拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string StringFormat()
{
string result = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += string.Format("{0} {1} {2}", StringPart1, StringPart2, StringPart3);
}
return result;
}
/// <summary>
/// 使用string.Concat()拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string StringConcat()
{
string result = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += string.Concat(StringPart1, " ", StringPart2, " ", StringPart3);
}
return result;
}
/// <summary>
/// 使用string.Join()拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string StringJoin()
{
string result = string.Empty;
for (int i = 0; i < IterationCount; i++)
{
result += string.Join(" ", _stringPartsArray);
}
return result;
}
/// <summary>
/// 使用StringBuilder拼接字符串
/// </summary>
/// <returns></returns>
[Benchmark]
public string StringBuilder()
{
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();
}
}
性能基准对比测试分析报告


| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|---|---|---|---|---|---|---|
| PlusOperator | 2,066.28 us | 35.761 us | 63.566 us | 5238.2813 | 789.0625 | 32283.12 KB |
| InterpolatedString | 1,984.56 us | 29.949 us | 28.014 us | 5238.2813 | 789.0625 | 32283.12 KB |
| StringFormat | 2,112.02 us | 25.020 us | 23.404 us | 5257.8125 | 777.3438 | 32369.06 KB |
| StringConcat | 2,027.09 us | 28.300 us | 26.472 us | 5257.8125 | 777.3438 | 32369.06 KB |
| StringJoin | 2,017.36 us | 27.111 us | 22.639 us | 5257.8125 | 777.3438 | 32369.06 KB |
| StringBuilder | 13.63 us | 0.065 us | 0.058 us | 23.2544 | 4.6387 | 143.96 KB |
说明:
- 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 秒)。
性能基准对比测试结论
从上面的性能基准对比测试分析报告来看StringBuilder是性能最好的字符串拼接方式,特别是在需要频繁进行拼接的场景中。其他方式(如+操作符、$内插字符串、String.Format、String.Concat和String.Join)在性能上相对较差,因为它们会导致多次内存分配和复制。
因此我们在选择字符串拼接方式时,应该根据具体场景和需求进行选择。如果性能是关键因素,并且需要频繁进行拼接,则应使用StringBuilder。如果代码简洁性和易读性更重要,并且拼接次数较少,则可以考虑使用其他方式。
C#字符串拼接的几种方式及其性能分析对比的更多相关文章
- JS几种变量交换方式以及性能分析对比
前言 "两个变量之间的值得交换",这是一个经典的话题,现在也有了很多的成熟解决方案,本文主要是列举几种常用的方案,进行大量计算并分析对比. 起由 最近做某个项目时,其中有一个需求是 ...
- JS几种数组遍历方式以及性能分析对比
前言 这一篇与上一篇 JS几种变量交换方式以及性能分析对比 属于同一个系列,本文继续分析JS中几种常用的数组遍历方式以及各自的性能对比 起由 在上一次分析了JS几种常用变量交换方式以及各自性能后,觉得 ...
- Python中字符串拼接的三种方式
在Python中,我们经常会遇到字符串的拼接问题,在这里我总结了三种字符串的拼接方式: 1.使用加号(+)号进行拼接 加号(+)号拼接是我第一次学习Python常用的方法,我们只需要把我们要加 ...
- Python字符串拼接的五种方式
第一种 通过加号(+)的形式 print('第一种方式通过加号形式连接 :' + 'love'+'Python' + '\n') 第二种 通过逗号(,)的形式 print('第二种方式通过逗号形式连接 ...
- java字符串拼接的几种方式
1. plus方式 当左右两个量其中有一个为String类型时,用plus方式可将两个量转成字符串并拼接. String a="";int b=0xb;String c=a+b;2 ...
- C#字符串拼接的三种方式
static void Main(string[] args) { string name = "asher"; //方法1 string str1 = "hello & ...
- [Golang]字符串拼接方式的性能分析
本文100%由本人(Haoxiang Ma)原创,如需转载请注明出处. 本文写于2019/02/16,基于Go 1.11.至于其他版本的Go SDK,如有出入请自行查阅其他资料. Overview 写 ...
- C 语言字符串连接的 3种方式
C 语言字符串连接的 3种方式 #include<stdio.h> #include<stdlib.h> #include<string.h> char *join ...
- Js 字符串拼接的两种方法
字符串拼接的两种方法 用数组的方法的好处是:避免变量重新定义.赋值 <!DOCTYPE html> <html lang="en"> <head> ...
- C++读取字符串数据的两种方式
C++读取字符串数据的两种方式 对于同样的样例输入: ladder came tape soon leader acme RIDE lone Dreis peat ScAlE orb eye Ride ...
随机推荐
- foobar2000 v2.1.3 汉化版(更新日期:2024.04.02)
foobar2000 v2.1.3 汉化版 -----------------------[软件截图]---------------------- -----------------------[软件 ...
- CentOS开放端口的方法(转载)
CentOS开放端口的方法 转载:https://www.itfeichai.com/centos-open-porter/ Centos升级到7之后,内置的防火墙已经从iptables变成了fire ...
- 如何修改word默认模板(Normal.dotm)
背景描述:平时有大量的文字编辑工作要做,其中最繁琐的就是格式问题:为了排版工整.符合要求,在每个word中都要进行大量的更改,如:字体.大小.行距.段前段后间距等......但这其中有很多的重复性工作 ...
- KubeSphere 社区双周报 | 苏州 Meetup 报名开启 | 2023.11.23-12.07
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- 快来考试拿证书!KubeSphere 个人技能专业考试认证上线啦!
以容器技术和容器编排为基础的云原生应用,被越来越多的企业用户接受和使用,并且在生产环境中使用容器技术的比例逐年增加.Kubernetes 无疑已经成为容器编排的事实基础,而依托于 Kubernetes ...
- KubeSphere 社区双周报 | 开源之夏已启动 | 2023.04.28-05.11
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- bash 连接操作符(& && | 等)的使用
链式操作(Chaining Operators),就是用于将多个命令组合在一起,根据操作符类型执行各种复杂指令.链式操作常用于你在交互shell中写下一长串指令执行的时候,它让shell脚本的自动化能 ...
- mysql文本数据导入
MySQL使用mysqlimport命令导入文本文件 MySQL中,可以使用mysqlimport命令将文本文件导入到MySQL数据库中.基本的语法格式如下: mysqlimport <dbna ...
- 历史性突破:独立开发 .net core 在线客服系统累计处理聊天消息 48 万余条!
业余时间用 .net core 写了一个在线客服系统.我把这款业余时间写的小系统丢在网上,陆续有人找我要私有化版本,我都给了,毕竟软件业的初衷就是免费和分享. 后来我索性就发了一个100%私有化版直接 ...
- docker bulid tag push到自己的docker hub 仓库
-t(或 --tag)参数:用于给构建的镜像指定标签(tag).标签的格式通常是 [仓库名/][用户名/]镜像名:版本号 -f(或 --file)参数: 指定构建镜像所使用的 Dockerfile 的 ...