前言

在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.FormatString.ConcatString.Join)在性能上相对较差,因为它们会导致多次内存分配和复制。

因此我们在选择字符串拼接方式时,应该根据具体场景和需求进行选择。如果性能是关键因素,并且需要频繁进行拼接,则应使用StringBuilder。如果代码简洁性和易读性更重要,并且拼接次数较少,则可以考虑使用其他方式。

C#字符串拼接的几种方式及其性能分析对比的更多相关文章

  1. JS几种变量交换方式以及性能分析对比

    前言 "两个变量之间的值得交换",这是一个经典的话题,现在也有了很多的成熟解决方案,本文主要是列举几种常用的方案,进行大量计算并分析对比. 起由 最近做某个项目时,其中有一个需求是 ...

  2. JS几种数组遍历方式以及性能分析对比

    前言 这一篇与上一篇 JS几种变量交换方式以及性能分析对比 属于同一个系列,本文继续分析JS中几种常用的数组遍历方式以及各自的性能对比 起由 在上一次分析了JS几种常用变量交换方式以及各自性能后,觉得 ...

  3. Python中字符串拼接的三种方式

    在Python中,我们经常会遇到字符串的拼接问题,在这里我总结了三种字符串的拼接方式:     1.使用加号(+)号进行拼接 加号(+)号拼接是我第一次学习Python常用的方法,我们只需要把我们要加 ...

  4. Python字符串拼接的五种方式

    第一种 通过加号(+)的形式 print('第一种方式通过加号形式连接 :' + 'love'+'Python' + '\n') 第二种 通过逗号(,)的形式 print('第二种方式通过逗号形式连接 ...

  5. java字符串拼接的几种方式

    1. plus方式 当左右两个量其中有一个为String类型时,用plus方式可将两个量转成字符串并拼接. String a="";int b=0xb;String c=a+b;2 ...

  6. C#字符串拼接的三种方式

    static void Main(string[] args) { string name = "asher"; //方法1 string str1 = "hello & ...

  7. [Golang]字符串拼接方式的性能分析

    本文100%由本人(Haoxiang Ma)原创,如需转载请注明出处. 本文写于2019/02/16,基于Go 1.11.至于其他版本的Go SDK,如有出入请自行查阅其他资料. Overview 写 ...

  8. C 语言字符串连接的 3种方式

    C 语言字符串连接的 3种方式 #include<stdio.h> #include<stdlib.h> #include<string.h> char *join ...

  9. Js 字符串拼接的两种方法

    字符串拼接的两种方法 用数组的方法的好处是:避免变量重新定义.赋值 <!DOCTYPE html> <html lang="en"> <head> ...

  10. C++读取字符串数据的两种方式

    C++读取字符串数据的两种方式 对于同样的样例输入: ladder came tape soon leader acme RIDE lone Dreis peat ScAlE orb eye Ride ...

随机推荐

  1. iOS关于NSNotificationCenter通知使用小结

    常用的页面之间传值方式是参数,单例,通知,委托,以及其他全局变量等等.通知是一种广播形式,可以一对多通知传值.最近在项目中用的模块化开发, 通过封装抽取,将页面分为上中下三个模块.最简单的方式是把所有 ...

  2. 58. vue常用的api

    1. nextTick  使用场景:通过异步渲染的页面解构不能直接dom操作,要使用 nextTick (延迟回调)等待一下 :nextTick 的作用:感知dom的更新完成,类似于 updated ...

  3. MySQL数据的导出

    有时需要将MySQL数据库中的数据导出到外部存储文件中,MySQL数据库中的数据可以导出成sql文本文件.xml文件或者html文件.本节将介绍数据导出的常用方法. 11.4.1  使用SELECT- ...

  4. 云原生动态周刊:你订阅 GitHub README 播客了吗?

    云原生一周动态要闻: Apache Kafka 3.0.0 发布 Deis Labs 推出 WebAssembly PaaS 平台 Hippo Mirantis Flow 将数据中心重塑为云原生系统 ...

  5. javascript 中==和===的区别【转载】

     javascript 中==和===的区别[转]     对于JavaScript中比较运算符,可能大家用的比较多的是"==".对于"==="很多人可能很陌生 ...

  6. CSS修改鼠标样式

    CSS可以修改鼠标样式,即将鼠标移到元素上时,自动切换为其他样式或者自定义图片. 设置属性cursor为各种鼠标形态(把鼠标移到标签上看效果): 标签 对应形态 auto 自动选择 crosshair ...

  7. AWS-最佳实践-杂信息

    1.Amazon Aurora Serverless v1 AmazonAurora-Serverless版本1是亚马逊Aurora的按需自动缩放配置.Aurora Serverlessv1 DB集群 ...

  8. 初探python栈帧逃逸

    前言 以前在一些大型比赛就遇到这种题,一直没时间去研究,现在康复训练下:) 生成器介绍 生成器(Generator)是Python中一种特殊的迭代器,它可以在迭代过程中动态生成值,而不需要一次性将所有 ...

  9. Go语言创建Web服务器

    因为Go语言自带高性能服务器,且支持http.TCP/UDP,这得益于内置了net/http包,这个包提供了HTTP客户端和服务端的实现, 所以用Go语言创建Web服务器,代码很简洁. 说明: 1.导 ...

  10. 银河麒麟操作系统root用户登录图形化界面

    第一步.为root用户设置密码 sudo passwd 设置root用户密码 第二步.开启root登录权限 vim /usr/share/lightdm/lightdm.conf.d/60-kylin ...