zoukankan      html  css  js  c++  java
  • StringBuilder,String.concat(),String+String 哪一个效率高

    今天,我在写C#代码时,突然发现一个最熟悉的陌生人 —— string.Format。在写C#代码的日子里,与它朝夕相伴,却没有真正去了解它。只知道在字符串比较多时,用它比用加号进行字符串连接效率更高(当然也更方便)。可是却从来没有问过为什么?

    在生活中也有类似的现象,与你朝夕相处、你最熟悉的人,你往往不会进一步去了解她(他),你已经习惯了她(他),你认为你已经太了解她(他)了。。。真的是这样吗?这值得去思考。。。

    博问中的一个问题 —— StringBuilder,String.concat(),String+String 哪一个效率高?  激发了我的好奇心,想一探string.Format的究竟,而且在开发中也正好遇到一个字符串连接的问题。

    了解.NET世界中的东西其实很简单,只要通过工具反编译出相应的.NET类库代码,我们来看看string.Fomat的代码:

    复制代码
        public static string Format(string format, object arg0, object arg1, object arg2)
        {
          if (format == null)
            throw new ArgumentNullException("format");
          return string.Format((IFormatProvider) null, format, arg0, arg1, arg2);
        }
    复制代码

    实际调用的是另外一个签名的string.Format:

    复制代码
        public static string Format(IFormatProvider provider, string format, params object[] args)
        {
          if (format == null || args == null)
            throw new ArgumentNullException(format == null ? "format" : "args");
          StringBuilder stringBuilder = new StringBuilder(format.Length + args.Length * 8);
          stringBuilder.AppendFormat(provider, format, args);
          return ((object) stringBuilder).ToString();
        }
    复制代码

    哦,原来用的就是StringBuilder(也许你早就知道了),string.Format只是StringBuilder的改装精简版。

    既然是StringBuilder,它必然无法避免一个影响StringBuilder性能的问题 —— 初始化容量(capacity)的问题,string.Format是如何解决的呢?从上面的代码一眼就可以看出,初始化容量是这么计算出来的:

    format.Length + args.Length * 8

    从这个计算公式可以看出,假设需要format的字符串是10个,如果这10字符串累加起来的字符数不超过80,就能发挥StringBuilder的最佳性能;否则,StringBuider需要扩容,从而带来性能损失。

    所以,对于大字符串,string.Format不是最佳选择。

    那最佳选择是什么?还是StringBuilder,只不过要自己写代码计算初始化容量。分享一下今天我们在实际开发中使用的代码:

    复制代码
    var bodyFormat = "<span id=\"comment_body_{0}\">{1}</span><br/>";                        
    var diggFormat = " <a href=\"javascript:void(0);\" onclick=\"voteComment({0},'Digg')\">支持({2})</a>";
    var buryFormat = " <a href=\"javascript:void(0);\" onclick=\"voteComment({0},'Bury')\">反对({3})</a>";
    var args = new string[]{ comment.ID.ToString(), comment.Body, comment.DiggCount.ToString(), comment.BuryCount.ToString() };
    //计算初始化容量
    int capacity = bodyFormat.Length + diggFormat.Length + buryFormat.Length;
    for (int i = 0; i < args.Length; i++)
    {
        capacity += args[i].Length;
    }
    var sb = new StringBuilder(capacity);
    sb.AppendFormat(bodyFormat,args); 
    sb.AppendFormat(diggFormat,args); 
    sb.AppendFormat(buryFormat,args);
    Post.Text = sb.ToString();
    复制代码

    这里没有使用string.Format,一是因为comment.Body的字符数会很多,string.Format分配的初始化容量不够。二是因为string.Format不能分批Fomat,格式字符串只能写在一起,造成格式字符串很长,也就是bodyFormat, diggFormat, buryFormat要拼成一个字符串。

    麻烦主要在参数字符串(args)的长度计算,要将每个字符串的字符数进行累加。我们采用的方法是将所有参数放在string[]类型的变量中,通过遍历数组进行计算,然后将这个string[]类型的变量直接传给StringBuilder.AppendFormat(它支持的参数类型是object[])。

    小结

    写这篇博文不是为让你弃用string.Format,而是让你了解它所存在的限制,在某些性能要求极高的场景下,可以考虑到这个影响因素。

     
     
  • 相关阅读:
    Windows JScript 在 游览器 中运行 调试 Shell 文件系统
    autohotkey 符号链接 软连接 symbolink
    软链接 硬链接 测试
    SolidWorks 修改 基准面 标准坐标系
    手机 路径 WebDAV 映射 驱动器
    Win10上手机路径
    explorer 命令行
    单位公司 网络 封锁 屏蔽 深信 AC
    cobbler自动化部署原理篇
    Docker四种网络模式
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2524385.html
Copyright © 2011-2022 走看看