我了解StringBuilder的好处。
但是如果我想连接2个字符串,那么我认为最好(更快)不使用StringBuilder。这正确吗?
在什么情况下(字符串数量)使用StringBuilder会更好?
我了解StringBuilder的好处。
但是如果我想连接2个字符串,那么我认为最好(更快)不使用StringBuilder。这正确吗?
在什么情况下(字符串数量)使用StringBuilder会更好?
我强烈建议您阅读Jeff Atwood的The Sad Tragedy of Micro-Optimization Theater,该文章与Simple Concatenation vs. StringBuilder以及其他方法有关。
现在,如果您想查看一些数字和图表,请点击链接;)
但如果我想连接两个字符串,那么我认为最好(更快)不使用 StringBuilder。这是正确的吗?
确实如此,你可以在以下链接中找到更详细的解释:
总结一下:如果你可以像下面这样一次性连接字符串:
var result = a + " " + b + " " + c + ..
如果只需要进行一次字符串拼接,那么使用StringBuilder可能不是最优的选择(因为结果字符串的长度可以预先计算得出);
对于类似结构的情况
var result = a;
result += " ";
result += b;
result += " ";
result += c;
..
每次都会创建新的对象,因此你应该考虑使用StringBuilder。System.String是一个不可变对象-这意味着每当您修改它的内容时,它都会分配一个新字符串,这需要时间(和内存?)。 使用StringBuilder,您可以修改对象的实际内容而无需分配新的字符串。
因此,当您需要对字符串进行多次修改时,请使用StringBuilder。
其实并不是这样的...如果你需要连接大量字符串或者有多次连接,比如在循环中,那么你应该使用StringBuilder。
StringBuilder
。 - Alex Bagnolinistring s = "abcd"
,至少这是我最后听到的...不过,对于变量来说,最可能的是使用Concat。 - Bobbya + "hello" + "somethingelse"
,从来不用担心它。如果它成为问题,我会使用 StringBuilder。但我一开始就没有担心它,写它花费的时间更少。 - Alex Bagnolini这是一个简单的测试应用程序,以证明这一点:
static void Main(string[] args)
{
//warm-up rounds:
Test(500);
Test(500);
//test rounds:
Test(500);
Test(1000);
Test(10000);
Test(50000);
Test(100000);
Console.ReadLine();
}
private static void Test(int iterations)
{
int testLength = iterations;
Console.WriteLine($"----{iterations}----");
//TEST 1 - String
var startTime = DateTime.Now;
var resultString = "test string";
for (var i = 0; i < testLength; i++)
{
resultString += i.ToString();
}
Console.WriteLine($"STR: {(DateTime.Now - startTime).TotalMilliseconds}");
//TEST 2 - StringBuilder
startTime = DateTime.Now;
var stringBuilder = new StringBuilder("test string");
for (var i = 0; i < testLength; i++)
{
stringBuilder.Append(i.ToString());
}
string resultString2 = stringBuilder.ToString();
Console.WriteLine($"StringBuilder: {(DateTime.Now - startTime).TotalMilliseconds}");
Console.WriteLine("---------------");
Console.WriteLine("");
}
结果(以毫秒为单位):
----500----
STR: 0.1254
StringBuilder: 0
---------------
----1000----
STR: 2.0232
StringBuilder: 0
---------------
----10000----
STR: 28.9963
StringBuilder: 0.9986
---------------
----50000----
STR: 1019.2592
StringBuilder: 4.0079
---------------
----100000----
STR: 11442.9467
StringBuilder: 10.0363
---------------
stringBuilder.ToString()
以使比较公平。 - nawfal为了表述清晰,我一般使用字符串构建器来连接三个或更多的字符串。
然后你要数到三,不多也不少。三应该是你要数的数字,而且计数的数字也应该是三。你不应该数四,也不应该数两个,除非你随后继续数到三。一旦达到第三个数字,即第三个数字,那么你就可以扔出你的安条克圣手榴弹了。
由于很难找到不受意见影响或跟随自豪心理的解释,所以我想在LINQpad上编写一些代码来测试它。
我发现使用小型字符串而不是使用i.ToString()可以改变响应时间(在小循环中可见)。
该测试使用不同的迭代序列以使时间测量在合理可比范围内。
我会在最后复制代码,这样您就可以尝试自己(results.Charts...Dump()
无法在LINQPad之外工作)。
输出(X轴:测试迭代次数,Y轴:消耗的时间,单位为Tick)
迭代序列:2, 3, 4, 5, 6, 7, 8, 9, 10
迭代序列:10, 20, 30, 40, 50, 60, 70, 80
代码(使用LINQPad 5编写):
void Main()
{
Test(2, 3, 4, 5, 6, 7, 8, 9, 10);
Test(10, 20, 30, 40, 50, 60, 70, 80);
Test(100, 200, 300, 400, 500);
}
void Test(params int[] iterationsCounts)
{
$"Iterations sequence: {string.Join(", ", iterationsCounts)}".Dump();
int testStringLength = 10;
RandomStringGenerator.Setup(testStringLength);
var sw = new System.Diagnostics.Stopwatch();
var results = new Dictionary<int, TimeSpan[]>();
// This call before starting to measure time removes initial overhead from first measurement
RandomStringGenerator.GetRandomString();
foreach (var iterationsCount in iterationsCounts)
{
TimeSpan elapsedForString, elapsedForSb;
// string
sw.Restart();
var str = string.Empty;
for (int i = 0; i < iterationsCount; i++)
{
str += RandomStringGenerator.GetRandomString();
}
sw.Stop();
elapsedForString = sw.Elapsed;
// string builder
sw.Restart();
var sb = new StringBuilder(string.Empty);
for (int i = 0; i < iterationsCount; i++)
{
sb.Append(RandomStringGenerator.GetRandomString());
}
sw.Stop();
elapsedForSb = sw.Elapsed;
results.Add(iterationsCount, new TimeSpan[] { elapsedForString, elapsedForSb });
}
// Results
results.Chart(r => r.Key)
.AddYSeries(r => r.Value[0].Ticks, LINQPad.Util.SeriesType.Line, "String")
.AddYSeries(r => r.Value[1].Ticks, LINQPad.Util.SeriesType.Line, "String Builder")
.DumpInline();
}
static class RandomStringGenerator
{
static Random r;
static string[] strings;
public static void Setup(int testStringLength)
{
r = new Random(DateTime.Now.Millisecond);
strings = new string[10];
for (int i = 0; i < strings.Length; i++)
{
strings[i] = Guid.NewGuid().ToString().Substring(0, testStringLength);
}
}
public static string GetRandomString()
{
var indx = r.Next(0, strings.Length);
return strings[indx];
}
}
没有确定的答案,只有经验法则。我的个人规则大致如下:
StringBuilder
。StringBuilder
。StringBuilder
。单个字符串拼接没有必要使用StringBuilder。通常我会以5个字符串拼接为一个经验法则。