C# 字符串链接

C#字符串链接经常使用的四种方式:StringBuilder、+、string.Format、List<string>。算法

1.+的方式sql

string sql = "update tableName set int1=" + int1.ToString() + ",int2=" + int2.ToString() + ",int3=" + int3.ToString() + " where id=" + id.ToString();app

编译器会优化为:ide

string sql = string.Concat(new string[]{});性能

经过分析string.Concat(params string[] values)的实现能够知道:先计算目标字符串的长度,而后申请相应的空间,最后逐一复制,时间复杂度为o(n),常数为1。优化

固定数量的字符串链接效率最高的是+。ui

可是字符串的连+不要拆成多条语句,好比:spa

string sql = "update tableName set int1=";
sql += int1.ToString();
sql += ....net

这样的代码,不会被优化为string.Concat,就变成了性能杀手,由于第i个字符串须要复制n-i次,时间复杂度就成了o(n^2)。code

2.StringBuilder的方式

StringBuilder 只分配一次内存,若是第二次链接内存不足,则修改内存大小;它每次默认分配16字节,若是内存不足,则扩展到32字节,若是仍然不足,继续成倍扩展。

若是频繁的扩展内存,效率大打折扣,由于分配内存,时间开销相对比较大。若是事先能准确估计程序执行过程当中所须要的内存,从而一次分配足内存,效率大大提升。

若是字符串的数量不固定,就用StringBuilder,通常状况下它使用2n的空间来保证o(n)的总体时间复杂度,常数项接近于2。

由于这个算法的实用与高效,.net类库里面有不少动态集合都采用这种牺牲空间换取时间的方式,通常来讲效果仍是不错的。

3.string.Format的方式

它的底层是StringBuilder,因此其效率与StringBuiler类似。

 1 public static string Format(IFormatProvider provider, string format, params object[] args)
 2 {
 3     if ((format == null) || (args == null))
 4     {
 5         throw new ArgumentNullException((format == null) ? "format" : "args");
 6     }
 7     StringBuilder sb = StringBuilderCache.Acquire(format.Length + (args.Length * 8));
 8     sb.AppendFormat(provider, format, args);
 9     return StringBuilderCache.GetStringAndRelease(sb);
10 }

 

4.List<string>它能够转换为string[]后使用string.Concat或string.Join,不少时候效率比StringBuiler更高效。List与StringBuilder采用的是一样的动态集合算法,时间复杂度也是O(n),与StringBuilder不一样的是:List的n是字符串的数量,复制的是字符串的引用;StringBuilder的n是字符串的长度,复制的数据。不一样的特性决定的它们各自的适应环境,当子串比较大时建议使用List<string>,由于复制引用比复制数据划算。而当子串比较小,好比平均长度小于8,特别是一个一个的字符,建议使用StringBuilder。

---------------------------

MSDN中关于StringBuilder的性能注意事项:

ConcatAppendFormat 方法都将新数据串连到一个现有的 String 或 StringBuilder 对象。String 对象串联操做老是用现有字符串和新数据建立新的对象。StringBuilder 对象维护一个缓冲区,以便容纳新数据的串联。若是有足够的空间,新数据将被追加到缓冲区的末尾;不然,将分配一个新的、更大的缓冲区,原始缓冲区中的数据被复制到新的缓冲区,而后将新数据追加到新的缓冲区。

String 或 StringBuilder 对象的串联操做的性能取决于内存分配的发生频率。String 串联操做每次都分配内存,而 StringBuilder 串联操做仅当 StringBuilder 对象缓冲区过小而没法容纳新数据时才分配内存。所以,若是串联固定数量的 String 对象,则 String 类更适合串联操做。这种状况下,编译器甚至会将各个串联操做组合到一个操做中。若是串联任意数量的字符串,则 StringBuilder 对象更适合串联操做;例如,某个循环对用户输入的任意数量的字符串进行串联。

相关文章
相关标签/搜索