如何将两个StringBuilder连接起来?

57

有没有一种方法可以将两个 StringBuilder 连接起来?如果可以的话,它比将一个字符串附加到 StringBuilder 上性能更好吗?


1
stringBuilder1.Append(stringBuilder2.ToString()); http://www.dotnetperls.com/stringbuilder-1 - Joe
1
我认为这个问题的命名不太合适! - Rosmarine Popcorn
6个回答

40

我知道现在已经过去了三年,但是.NET 4版本的 StringBuilder 行为不同了。

尽管如此,问题仍然归结于“你想做什么?”你是只想找到最高效的方法将两个StringBuilders连接起来,然后继续使用后者的结果?还是希望继续使用已连接StringBuilder的缓冲值?

对于前者,在.NET 4中始终如此:

frontStringBuilder.Append(backStringBuilder);

是最好的。

对于.NET 2/3.5中的后一种情况,

frontStringBuilder.Append(backStringBuilder.ToString(0, backStringBuilder.Length));

是最好的选择(且不会影响.NET 4的性能)。


非常清晰的答案。我认为值得补充的是,如果有人想知道,.AppendLine()不提供相同的灵活性。 - Charles Roberto Canato
@CharlesRobertoCanato 我不确定你的意思:.AppendLine 在 .NET 2.0/3.5 和 4 中都是通过 .Append(string) 后跟 .Append(NewLine) 实现的,这意味着上述两种情况是相同的。 - Mark Hurd
1
很抱歉@MarkHurd,我的表述不够清晰:我想表达的是,尽管.AppendLine确实是按照你所描述的实现的,但在任何.NET版本中,它只接受String作为参数。所以,即使在.NET 4中,你也不能仅通过.AppendLine( backStringBuilder )来完成 - 这就是我所说的"缺乏灵活性"。这不是问题,只是一个注意点 - 无论如何,它只是一个额外的方法调用。 - Charles Roberto Canato
@CharlesRobertoCanato 实际上,您正在突出显示代码的最近更改:我删除了显式的.ToString,因为正如Nigrimmist在他的答案中提到的那样,.ToString目前是隐含的,并且将来可能会有一个重载版本直接接受StringBuilder - Mark Hurd
7
在幕后,frontStringBuilder.Append(backStringBuilder) 调用了 backStringBuilder.toString()。因此它基本上是 frontStringBuilder.Append(backStringBuilder.ToString()) - rovsen
2
@rovsen 是的,那就是我一开始的想法,直到 Nigrimmist 指出如果未来可能会有 StringBuilder 直接重载的可能性,那么最好这样做。 - Mark Hurd

24

就像那样....

StringBuilder sb = new StringBuilder();
StringBuilder sb1 = new StringBuilder();
sb.Append(sb1.ToString());

51
这是将字符串附加到sb。我想附加到sb以避免将sb封闭为字符串。 - Elad Benda

19

这将在不分配内存的情况下完成

StringBuilder sb = new StringBuilder("aaaa");    
StringBuilder second = new StringBuilder("bbbbb");
sb.EnsureCapacity(sb.Length + second.Length);
for (int i = 0; i < second.Length; i++)
{
    sb.Append(second[i]);
}

3
不幸的是,StringBuilder 中的索引器属性是不平凡的,实际上会在每次访问时迭代 StringBuilder 内的每个“块”,这使得在循环中使用它相对昂贵。对于我的实现,如果 StringBuilder 长度超过约 4,000 个字符,则使用可重用的 Char[] 缓冲区。 - Dai

14
你不需要调用 .ToString(),你应该简单地将一个附加到另一个上。这样做比直接调用.ToString()更好的原因是:

1)StringBuilder没有以StringBuilder为参数的构造函数,只有string、int/string等类型。 StringBuilder重写了.ToString()方法,因此:
StringBuilder sb1 = new StringBuilder("1");
sb1.Append(new StringBuilder("2"));
Console.WriteLine(sb1);

代码将自动调用已重写的.ToString()版本。输出将为"12"

2) 如果下一个框架版本中将StringBuilder添加为传入参数到StringBuilder构造函数中,您的代码将清晰且无需进行任何重构即可准备好正确地附加。

祝您有美好的一天!


1
很棒的建议和清晰易懂的编码。 - Roel van Megen

5
如果 StringBuilder 很大,则这将最小化字符串分配(特别是如果您可以提供可重用的 char 缓冲区):
    public static void CopyTo(this StringBuilder source, StringBuilder dest)
    {
        char[] buffer = new char[Math.Min(source.Length, 1024)];
        CopyTo(source, dest, buffer);
    }

    public static void CopyTo(this StringBuilder source, StringBuilder dest, char[] buffer)
    {
        dest.EnsureCapacity(dest.Length + source.Length);
        for (int i = 0; i < source.Length; i += buffer.Length)
        {
            int charCount = Math.Min(source.Length - i, buffer.Length);
            source.CopyTo(i, buffer, 0, charCount);
            dest.Append(buffer, 0, charCount);
        }
    }

4
就这么简单:
firstStringBuilder.Append(secondStringBuilder.ToString());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接