string html =string.empty;
DataView dV = data.DefaultView;
for(int i=0;i< dV.Count;i++)
{
DataRowView rv = dV[i];
html += rv.Row["X"].Tostring();
}
dV中的行数始终为3或4。
在这种情况下,使用字符串连接符 += 还是 StringBuilder 更好?为什么?
string html =string.empty;
DataView dV = data.DefaultView;
for(int i=0;i< dV.Count;i++)
{
DataRowView rv = dV[i];
html += rv.Row["X"].Tostring();
}
dV中的行数始终为3或4。
在这种情况下,使用字符串连接符 += 还是 StringBuilder 更好?为什么?
我建议在这里使用 StringBuilder
,因为它可以描述你正在做的事情。
如果只是简单地连接 3 或 4 个字符串,可能不会产生任何显着差异,甚至字符串连接 可能 会略微更快 - 但如果你的假设错误,并且有很多行,StringBuilder
将变得更加高效,而且它总是更能清楚地表述你的操作。
或者,可以使用类似下面的东西:
string html = string.Join("", dv.Cast<DataRowView>()
.Select(rv => rv.Row["X"]));
请注意,您目前在字符串之间没有任何分隔符。您确定这就是您想要的吗?(还要注意,您的代码当前并没有太多意义 - 在循环中您并没有使用i
。为什么?)
我有一篇关于字符串连接的文章,其中更详细地讨论了为什么值得使用StringBuilder
以及何时使用。
编辑:对于那些怀疑字符串连接速度更快的人,这里有一个测试 - 使用故意“恶劣”的数据,但只是为了证明它是可能的:
using System;
using System.Diagnostics;
using System.Text;
class Test
{
static readonly string[] Bits = {
"small string",
"string which is a bit longer",
"stirng which is longer again to force yet another copy with any luck"
};
static readonly int ExpectedLength = string.Join("", Bits).Length;
static void Main()
{
Time(StringBuilderTest);
Time(ConcatenateTest);
}
static void Time(Action action)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
// Make sure it's JITted
action();
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
action();
}
sw.Stop();
Console.WriteLine("{0}: {1} millis", action.Method.Name,
(long) sw.Elapsed.TotalMilliseconds);
}
static void ConcatenateTest()
{
string x = "";
foreach (string bit in Bits)
{
x += bit;
}
// Force a validation to prevent dodgy optimizations
if (x.Length != ExpectedLength)
{
throw new Exception("Eek!");
}
}
static void StringBuilderTest()
{
StringBuilder builder = new StringBuilder();
foreach (string bit in Bits)
{
builder.Append(bit);
}
string x = builder.ToString();
// Force a validation to prevent dodgy optimizations
if (x.Length != ExpectedLength)
{
throw new Exception("Eek!");
}
}
}
在我的计算机上运行的结果(使用/o+ /debug-
编译):
StringBuilderTest: 2245 millis
ConcatenateTest: 989 millis
我已经运行了这个测试多次,包括反转测试顺序,结果是一致的。
StringBuilder
在每次连接时都必须复制数据,则字符串连接可能会更快。首先需要一个StringBuilder
对象,而调用ToString
会进行额外的复制。请注意,在.NET 3.5和.NET 4之间,StringBuilder
的实现发生了重大变化,但我仍然期望对于三到四个字符串使用字符串连接有时会更快。请注意,我并不推荐这样做。 - Jon Skeet建议使用StringBuilder..为什么不自己进行分析,然后决定哪个对您最好..
var stopWatch=new StopWatch();
stopWatch.Start();
string html =string.empty;
DataView dV = data.DefaultView;
for(int i=0;i< dV.Count;i++)
{
html += dV.Row["X"].Tostring();
}
stopWatch.Stop();
Console.Write(stopWatch.EllapsedMilliseconds());
var stopWatch=new StopWatch();
stopWatch.Start();
string html =new StringBuilder();
DataView dV = data.DefaultView;
for(int i=0;i< dV.Count;i++)
{
html.Append(dV.Row["X"].ToString());
}
var finalHtml=html.ToString();
stopWatch.Stop();
Console.Write(stopWatch.EllapsedMilliseconds());
StringBuilder
更清晰地表达了你的意图。 - Jon Skeet"abc" + "def" + "ghi"
,它有可能将其合并为单个操作,就像您在帖子中所写的那样,但对于典型的循环,编译器无法知道循环次数,因此每个循环中都会有一次操作。这也是为什么循环展开是性能优化的原因。简单地说,“如果固定数量的字符串对象被连接”这个条件并不成立,因为即使您知道有3或4个项目,编译器也不知道。 - BetlistaStringBuilder 当然没问题。记住字符串是不可变的!
编辑:对于3-4行,像Jon Skeet在他的回答中所说的那样,连接将是更好的选择。
StringBuilder
更慢。特别是当 StringBuilder
需要在每次 Append
时扩展时,你仍然需要进行所有的复制开销,但是你还需要进行最终的复制操作和 StringBuilder
本身的开销。 - Jon Skeet你要找的是 StringBuilder。通常,如果有一个函数可以完成某项工作,请尽量利用它,而不是编写几乎相同的过程。