所以......我有这个场景,我有一个Foreach循环,循环通过一个复选框列表来检查选中哪个。对于每个选中的复选框,我必须进行相当长的字符串连接,涉及30个平均长度为20个字符的不同字符串,然后将其作为HTTP请求发送出去。其中2个字符串取决于所选复选框的索引/值。
复选框列表的长度也可根据用户的数据而变化。我会说List的平均长度是20,但它可以达到50-60。因此,最糟糕的情况是整个字符串连接执行60次左右。
现在我通过'+'运算符进行简单的字符串连接,但是我想知道使用Stringbuilder进行简单的连接是否会更快。当然,这意味着我必须在循环中创建一个Stringbuilder对象,或者在循环之前创建它,并在发出HTTP请求后调用Stringbuilder.Remove。
我感谢任何人可以就此问题分享任何见解。
修改
感谢大家的所有回复,所以从我收集的内容来看,我这样做的最佳方式是:
StringBuilder sb = new StringBuilder();
foreach (CheckBox item in FriendCheckboxList)
{
if (item.Checked)
{
sb.Append(string1);
sb.Append(string2);
sb.Append(string3);
.
.
.
sb.Append(stringLast);
SendRequest(sb.ToString());
sb.Length = 0;
}
}
答案 0 :(得分:14)
使用StringBuilder
。这就是它的用途。
字符串是不可变的。字符串连接会创建一个新字符串,需要更多内存,通常被认为很慢:
string a = "John" + " " + "Saunders";
这会创建一个字符串“John”,然后创建另一个字符串“John Saunders”,最后将其分配给“a”。 “John”留给垃圾收集。
string a = "John";
a += " ";
a += "Saunders";
这大致相同,因为“John”被新的字符串“John”取代,后者被新的字符串“John Saunders”取代。原件留给垃圾收集。
另一方面,StringBuilder
旨在追加,删除等等。
示例:
StringBuilder sb = new StringBuilder();
for (int i=0; i<n; i++)
{
sb.Length = 0;
sb.Append(field1[i]);
sb.Append(field2[i]);
...
sb.Append(field30[i]);
// Do something with sb.ToString();
}
答案 1 :(得分:7)
这个主题多年来一直被分析为死亡。最终结果是,如果要进行少量已知的连接,请使用“+”,否则请使用stringbuilder。从你所说的,与'+'连接应该更快。有很多(赠送或采取)网站在那里分析这个 - 谷歌。
对于你所谈论的字符串的大小,它无论如何都可以忽略不计。
编辑:第二个想法,SB可能更快。但就像我说的,谁在乎?答案 2 :(得分:7)
我知道这已经得到了回答,但我想指出我实际上认为总是使用StringBuilder的“盲目接受的福音”方法有时是错误的,这是一个案例。
有关背景信息,请参阅此博客文章:http://geekswithblogs.net/johnsperfblog/archive/2005/05/27/40777.aspx
缺点是,对于这种特殊情况,如上所述,通过避免使用StringBuilder并使用+运算符,您将看到更好的性能:
foreach (CheckBox item in FriendCheckboxList)
{
if (item.Checked)
{
string request = string1 +
string2 +
string3 +
.
.
.
stringLast;
SendRequest(request);
}
}
原因是C#编译器(从.NET 1.1开始)将该语句转换为对String.Concat的单个IL调用,并将Strings数组作为参数传递。博客条目在概述String.Concat的实现细节方面做得非常出色,但足以说明,它对于这种情况非常有效。
答案 3 :(得分:2)
一般情况下,我建议使用StringBuilder
。
您是否对此进行了测试并检查了性能? 性能是一个问题与重写代码需要多长时间?
答案 4 :(得分:2)
如果你问这个问题,很可能你应该使用StringBuilder有很多原因,但我会提供两个。
使用字符串连接时,必须分配新的缓冲区,并将另一个字符串中的数据复制到新的字符串变量中。因此,您将需要多次重复分配。这最终会破坏内存,使用堆空间,并为垃圾收集器做更多的工作。 另一方面,StringBuilder预先分配一个缓冲区,当你向它添加字符串时,不需要保持重新分配(假设初始缓冲区足够大)。这提高了性能,对内存的负担也大大降低。
作为开发者,我们应该尝试预测未来的增长。假设您的列表随着时间的推移而大幅增长,然后突然开始缓慢执行。如果你现在可以毫不费力地防止这种情况,你为什么不这样做呢?