当我需要连接两个字符串我使用的String.Format(或StringBuilder的,如果它发生在几个地方在代码中)。
我看到一些优秀的程序员没有给予重视字符串连接复杂,只是用“+”操作符。
我知道,用“+”操作符使应用程序能够使用更多的内存,但对于复杂性?
当我需要连接两个字符串我使用的String.Format(或StringBuilder的,如果它发生在几个地方在代码中)。
我看到一些优秀的程序员没有给予重视字符串连接复杂,只是用“+”操作符。
我知道,用“+”操作符使应用程序能够使用更多的内存,但对于复杂性?
这是关于不同的字符串参加由我们自己的杰夫阿特伍德对编码恐怖方法的优秀文章:
(来源: codinghorror.com )
微优化剧院哀伤的悲剧
下面是文章的主旨。
[ 数串加入所示的方法 ]
把你的痒的小扣扳机的手指关闭该编译键,想想这个一分钟。 其中这些方法中的一个会更快?
有一个答案? 大!
和..击鼓声请..正确答案:
它。 只是。 不。 物!
这个回答假设你正在谈论的运行复杂性。
使用+
创建一个新的字符串对象,这意味着同时以旧的字符串对象中的内容必须被复制到新的。 用大量级联的,例如在紧密循环,这可以变成为O(n ^ 2)的操作。
作为一个非正式的证据,说你有下面的代码:
string foo = "a";
for(int i = 0; i < 1000; i++)
{
foo += "a";
}
该循环的第一次迭代中,第一内容foo
(“A”)被复制到一个新的字符串对象,则文字“a”的内容。 这两个副本。 第二次迭代有三个副本; 两个来自新foo
,和一个从字面“一”。 第1000个迭代将有1001个复制操作。 副本的总数是2 + 3 + ... + 1001
。 一般来说,如果在一个循环,你只串联一个字符每次迭代(和你在一个字符开始),如果迭代次数为n,将有2 + 3 + ... + n + 1
副本。 这是相同的1 + 2 + 3 + ... + n = n(n+1)/2 = (n^2 + n)/2
,这是O(n ^ 2)。
视情况而定。 该+有时可以减少代码的复杂性。 考虑下面的代码:
output = "<p>" + intro + "</p>";
这是一个很好的,线条清晰。 不需要的String.Format。
如果使用+只有一次,你有没有从它的缺点,它增加了可读性(如科林·皮卡德已经提到)。
据我所知+的意思是:取左操作数和右操作数,并将它们复制到一个新的缓冲区(string是不可改变的)。
因此添加时使用+两次(如科林Pickards例如,你已经创造2个临时字符串。首先"<p>"
加入时INTRO然后"</p>"
到新创建的字符串。
你必须考虑自己时使用的方法。 即使是一个小例子,如果介绍是一个足够大的串像上面说的性能下降,严重者可发生。
除非你的应用程序是非常字符串密集型(型材,异型材,异型材!),这其实并不重要。 好的程序员把上面世俗操作的性能可读性。
我认为,在复杂性方面你交易的新创建的字符串重申解析格式字符串。 对于axample "A" + "B" + "C" + "D"
意味着你将不得不为“A”,“AB”复制,并在最后的“ABC”,以形成“ABCD”。 复制是重申,对不对? 因此,例如,如果你有一个1000字符串,你将有一千字符串将复制(1000 + N)字符串1000次总结。 这导致为O(n ^ 2)复杂性在最坏的情况下。
Strin.Fomat,即使考虑解析,和StringBuffer应该是大约为O(n)。
因为字符串是像Java和C#,语言不可改变每次两个字符串串接一个新的字符串已经被创建,其中两个老串的内容被复制。
假设字符串这些都对平均C字符。
现在,第一个串联只需要复制2个* C字符,但最后一个具有复制的第n-1个字符串的连接,这是长(N-1)* C字符,而最后一个本身,这是ç字符长,总共n个* C的字符。 对于n级联这使得N ^ 2 * C / 2字符拷贝,这意味着的O的算法的复杂性(N ^ 2)。
在大多数情况下,在实践然而这二次的复杂性不会明显(如杰夫阿特伍德显示了由罗伯特C. Cartaino链接到博客条目),我会建议只写尽可能地易读的代码。
在有些情况下物质然而当它,并且在这样的情况下,使用为O(n ^ 2)可以是致命的。
在实践中我已经看到了这个例如在内存中产生大的Word XML文件,其中包括base64编码图片。 这一代用于采取由于使用为O(n ^ 2)的字符串连接在10分钟内。 后我使用+与StringBuilder的用于相同的文档减小到低于10秒的运行时间替换串联。
同样地,我见过的软件,生成一个epically大片的SQL代码使用+进行连结的字符串。 我还没有等到这个成品(已早已经等候了一个多小时),只是重写了它使用的StringBuilder。 这更快的版本在一分钟内完成。
总之,只要做什么是最可读/最容易写,只想想这个,当你将创建一个巨大再用字符串:-)
StringBuilder的应该,如果你正在建设中的几个步骤,一个大的字符串中使用。 它也是一个很好的事情,如果你知道它会多大,最终,那么你就可以用你需要的大小初始化,防止成本重新分配。 对于小的操作也不会使用+运营商相当大的性能损失,而且会导致更清晰的代码(和更快的写的...)
输入充沛了,但我一直认为,接近的性能问题的最好办法就是了解所有可行的解决方案的性能差异,对于那些满足性能要求,挑选一个是最可靠和最支持的。
有很多谁使用大O表示法来理解复杂性,但我发现,在大多数情况下(包括了解哪些字符串连接方法效果最好),一个简单的计时赛就足够了。 就在10万次迭代循环比较STRA + STRB到strA.Append(STRB),看看哪些工作得更快。
编译器优化字符串文字串联成一个字符串常量。 例如:
string s = "a" + "b" + "c";
被优化以在编译时的情况如下:
string s = "abc";
见这个问题和这个MSDN文章以获取更多信息。
编译器将优化:“A” +“B” +“C”将与String.Concat方法(未的String.format一个为固定我的意见)代替
我这个基准很久以前,它并没有真正做,因为.NET 1.0或1.1的差异。
那时候,如果你有一些过程,会打一条线的这是concatinating串几百万次,你可以得到使用String.Concat,的String.Format或StringBuilder的速度有很大的提高代码。
现在,没关系的。 至少从NET 2.0出来了,无论如何它不是重要的。 把它放在你的头脑和代码以任何方式使得你最容易阅读的。