casperOne 完全准确,这取决于数据。但是,假设您将其作为类库编写以供第 3 方使用 - 您会使用哪个?
一种选择是两全其美 - 计算出您实际上需要附加多少数据,然后使用StringBuilder.EnsureCapacity确保我们只需要调整单个缓冲区大小。
如果我不太介意的话,我会使用Append
x3 - 似乎“更有可能”更快,因为在每次调用时解析字符串格式标记显然是制作工作。
请注意,我已经向 BCL 团队询问了一种“缓存格式化程序”,我们可以使用格式字符串创建它,然后重复使用。框架每次使用时都必须解析格式字符串,这太疯狂了。
编辑:好的,为了灵活性,我对 John 的代码进行了一些编辑,并添加了一个“AppendWithCapacity”,它首先计算出必要的容量。以下是不同长度的结果 - 对于长度 1,我使用了 1,000,000 次迭代;对于所有其他长度,我使用了 100,000。(这只是为了获得合理的运行时间。)所有时间都以毫秒为单位。
不幸的是,表格在 SO 中并没有真正起作用。长度分别为 1、1000、10000、20000
时间:
- 追加:162、475、7997、17970
- 附加格式:392、499、8541、18993
- 附加容量:139、189、1558、3085
事情发生了,我从未见过 AppendFormat 击败 Append - 但我确实看到 AppendWithCapacity 以非常可观的优势获胜。
这是完整的代码:
using System;
using System.Diagnostics;
using System.Text;
public class StringBuilderTest
{
static void Append(string string1, string string2)
{
StringBuilder sb = new StringBuilder();
sb.Append(string1);
sb.Append("----");
sb.Append(string2);
}
static void AppendWithCapacity(string string1, string string2)
{
int capacity = string1.Length + string2.Length + 4;
StringBuilder sb = new StringBuilder(capacity);
sb.Append(string1);
sb.Append("----");
sb.Append(string2);
}
static void AppendFormat(string string1, string string2)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}----{1}", string1, string2);
}
static void Main(string[] args)
{
int size = int.Parse(args[0]);
int iterations = int.Parse(args[1]);
string method = args[2];
Action<string,string> action;
switch (method)
{
case "Append": action = Append; break;
case "AppendWithCapacity": action = AppendWithCapacity; break;
case "AppendFormat": action = AppendFormat; break;
default: throw new ArgumentException();
}
string string1 = new string('x', size);
string string2 = new string('y', size);
// Make sure it's JITted
action(string1, string2);
GC.Collect();
Stopwatch sw = Stopwatch.StartNew();
for (int i=0; i < iterations; i++)
{
action(string1, string2);
}
sw.Stop();
Console.WriteLine("Time: {0}ms", (int) sw.ElapsedMilliseconds);
}
}