如何明智地使用StringBuilder?

Bar*_*zek 66 .net c# memory string stringbuilder

我对使用StringBuilder课程感到困惑,首先:

一个string对象串联操作总是创建从现有的一个新的对象string和新的数据.甲StringBuilder对象维护一个缓冲器,以适应新的数据的串联.如果房间可用,新数据将附加到缓冲区的末尾; 否则,分配一个新的较大缓冲区,将原始缓冲区中的数据复制到新缓冲区,然后将新数据附加到新缓冲区.

但是创建StringBuilder实例以避免创建新实例的重点在哪里String?这听起来像是"一对一"交易.

static void Main(string[] args)
{
    String foo = "123";
    using (StringBuilder sb = new StringBuilder(foo)) // also sb isn't disposable, so there will be error
    {
        sb.Append("456");
        foo = sb.ToString();
    }

    Console.WriteLine(foo);
    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

为什么我不应该只使用

+=
Run Code Online (Sandbox Code Playgroud)

编辑:好的,我现在知道如何重用的一个实例StringBuilder(仍然不知道这是否是正确的代码标准),但是这是不值得的只有一个使用string的,不是吗?

Tam*_*red 101

修改像s 这样的不可变结构string必须通过复制结构来完成,这样就消耗了更多内存并减慢了应用程序的运行时间(也增加了GC时间等等).

StringBuilder 通过使用相同的可变对象进行操作来解决这个问题.

然而:

string在编译时连接如下:

string myString = "123";
myString += "234";
myString += "345";
Run Code Online (Sandbox Code Playgroud)

它实际上会编译成类似的东西:

string myString = string.Concat("123", "234", "345");
Run Code Online (Sandbox Code Playgroud)

此功能比使用进入该功能StringBuilderstrings 的数量更快.

所以对于编译时已知的string连接,你应该更喜欢string.Concat().

对于string以下情况中未知数量的喜欢:

string myString = "123";
if (Console.ReadLine() == "a")
{
    myString += "234";
}
myString += "345";
Run Code Online (Sandbox Code Playgroud)

现在编译器不能使用该string.Concat()函数,但是,StringBuilder只有当连接完成6-7或更多时,才能在时间和内存消耗方面更有效strings.

不良做法用法:

StringBuilder myString = new StringBuilder("123");
myString.Append("234");
myString.Append("345");
Run Code Online (Sandbox Code Playgroud)

精细练习用法(注意if使用):

StringBuilder myString = new StringBuilder("123");
if (Console.ReadLine() == "a")
{
    myString.Append("234");
}
myString.Append("345");
Run Code Online (Sandbox Code Playgroud)

最佳实践用法(请注意使用while循环):

StringBuilder myString = new StringBuilder("123");
while (Console.ReadLine() == "a")
{
    myString.Append("234"); //Average loop times 4~ or more
}
myString.Append("345");
Run Code Online (Sandbox Code Playgroud)

  • 啊,谢谢你.我必须阅读100次并仍然错过它. (3认同)
  • @JaimieKnox注意`while` /`if`和评论. (2认同)

Dir*_*irk 13

A string是一个不可变的类.您无法修改它,只能创建新的strings.

所以当你写的时候,你在那个点上result += a;有三个独立strings的内存:a旧值result和新值.当然,如果你只连接有限的数量,这绝对没问题strings.如果你在for迭代大型集合的循环中这样做,它可能会成为一个问题.

StringBuilder在这些情况下,该课程提供了改进的性能 strings它不使用new 来存储连接结果,而是使用相同的对象.所以如果你使用stringBuilder.Append(a);你永远不会有相当于"旧的价值result".


当然,这种内存效率是有代价的.当仅连接少量的stringsa StringBuilder在速度方面通常效率较低时,因为与不可变string类相比,它具有更多的开销.


要记住的一件事是,当你需要中间字符串时,StringBuilder由于调用.ToString()它会产生新的副本,因此效率会降低string.