我理解StringBuilder的好处.
但是如果我想连接2个字符串,那么我认为没有StringBuilder它会更好(更快).它是否正确?
在什么时候(字符串的数量)使用StringBuilder会变得更好?
Ale*_*ini 72
我热烈建议你阅读杰夫阿特伍德的微观优化剧场悲剧悲剧.
它将Simple Concatenation与StringBuilder与其他方法相比较.
现在,如果您想查看一些数字和图表,请点击链接;)
Pet*_*ter 40
但是如果我想要连接2个字符串,那么我认为没有StringBuilder它会更好(更快).它是否正确?
这确实是正确的,你可以找到为什么完全解释得很好:
http://www.yoda.arachsys.com/csharp/stringbuilder.html
总结一下:如果你可以一次性结合字符串
var result = a + " " + b + " " + c + ..
Run Code Online (Sandbox Code Playgroud)
如果没有StringBuilder,你最好只在复制时(最终计算得到的字符串的长度.);
像结构一样
var result = a;
result += " ";
result += b;
result += " ";
result += c;
..
Run Code Online (Sandbox Code Playgroud)
每次都会创建新对象,因此您应该考虑使用StringBuilder.
最后,文章总结了这些经验法则:
经验法则
那么,什么时候应该使用StringBuilder,何时应该使用字符串连接运算符?
当您在一个非平凡的循环中连接时,肯定会使用StringBuilder - 特别是如果您不确定(在编译时)您将通过循环进行多少次迭代.例如,一次读取一个文件,使用+ =运算符构建一个字符串可能会导致性能自杀.
当你可以(可读地)指定需要在一个语句中连接的所有内容时,绝对使用连接运算符.(如果要连接的数组,请考虑显式调用String.Concat - 如果需要分隔符,请考虑String.Join.)
不要害怕将文字分成几个连接位 - 结果将是相同的.例如,您可以通过将长文字分成几行来提高可读性,而不会损害性能.
如果您需要连接的中间结果,而不是提供下一次连接迭代,StringBuilder不会帮助您.例如,如果你从名字和姓氏建立一个全名,然后在最后添加第三条信息(昵称,也许),你只会受益于使用StringBuilder,如果你不这样做需要(名字+姓氏)字符串用于其他目的(正如我们在创建Person对象的示例中所做的那样).
如果你只是有几个串连的事,和你真正想要做他们单独的语句,它并没有真正不管你走哪条路.哪种方法更有效,将取决于级联串的大小参与的数量,和他们连接在一起的顺序.如果你真的相信这段代码是一个性能瓶颈,配置文件或基准两者兼得.
Vic*_*aci 11
System.String是一个不可变对象 - 这意味着无论何时修改其内容,它都会分配一个新字符串,这需要时间(和内存?).使用StringBuilder可以修改对象的实际内容,而无需分配新对象.
因此,当您需要对字符串进行许多修改时,请使用StringBuilder.
不是......如果你连接大字符串或者你有许多连接,你应该使用StringBuilder ,就像在循环中一样.
没有明确的答案,只有经验法则。我自己的个人规则是这样的:
StringBuilder
.StringBuilder
.StringBuilder
.转述
然后你数到三,不多也不少。三是你要数的数,数的数是三。四你不要数,你也不要数二,除非你继续到三。一旦达到第三个数字,即第三个数字,然后向你挥舞你的安条克圣手手榴弹
我通常将字符串生成器用于任何会导致三个或更多字符串连接的代码块。
这是一个简单的测试应用程序来证明这一点:
class Program
{
static void Main(string[] args)
{
const int testLength = 30000;
var StartTime = DateTime.Now;
//TEST 1 - String
StartTime = DateTime.Now;
String tString = "test string";
for (int i = 0; i < testLength; i++)
{
tString += i.ToString();
}
Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString());
//result: 2000 ms
//TEST 2 - StringBuilder
StartTime = DateTime.Now;
StringBuilder tSB = new StringBuilder("test string");
for (int i = 0; i < testLength; i++)
{
tSB.Append(i.ToString());
}
Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString());
//result: 4 ms
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
30'000次迭代
1000次迭代
500次迭代
由于很难找到一个既不受观点影响又不受骄傲之战影响的解释,因此我想在 LINQpad 上编写一些代码来自己测试一下。
我发现使用小尺寸的字符串而不是使用 i.ToString() 会改变响应时间(在小循环中可见)。
该测试使用不同的迭代序列来将时间测量保持在合理可比较的范围内。
我将在最后复制代码,以便您可以自己尝试(results.Charts...Dump()
在 LINQPad 之外不起作用)。
输出(X 轴:测试的迭代次数,Y 轴:以刻度为单位花费的时间):
代码(使用 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];
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
32992 次 |
最近记录: |