代码之家  ›  专栏  ›  技术社区  ›  Bartłomiej Sobieszek

如何明智地使用StringBuilder?

  •  74
  • Bartłomiej Sobieszek  · 技术社区  · 11 年前

    我对使用 StringBuilder 第一类:

    A. string 对象连接操作始终从现有对象创建新对象 一串 以及新数据。A. 字符串拼接 对象维护缓冲区以容纳新数据的连接。如果有可用空间,新数据将附加到缓冲区的末尾;否则,分配一个新的、更大的缓冲区,将原始缓冲区中的数据复制到新缓冲区,然后将新数据附加到新的缓冲区。

    但创造的意义何在 字符串拼接 实例以避免创建新的 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();
    }
    

    为什么我不应该使用

    +=
    

    编辑: 好的,我现在知道如何重用 字符串拼接 (仍然不知道这是否适用于代码标准),但这不值得仅用于一个 一串 不是吗?

    3 回复  |  直到 6 年前
        1
  •  112
  •   Tamir Vered    8 年前

    修改 immutable 结构,如 string 必须通过复制结构来完成,这样会消耗更多的内存并降低应用程序的运行时间(也会增加 GC 时间等)。

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

    然而:

    连接 一串 编译时如下:

    string myString = "123";
    myString += "234";
    myString += "345";
    

    它实际上会编译成这样:

    string myString = string.Concat("123", "234", "345");
    

    此函数比使用 字符串拼接 对于 一串 s进入函数是已知的。

    所以对于已知的编译时间 一串 你应该喜欢的串联 string.Concat() .

    至于未知数量的 一串 如以下情况:

    string myString = "123";
    if (Console.ReadLine() == "a")
    {
        myString += "234";
    }
    myString += "345";
    

    现在编译器不能使用 string.Concat() 然而, 字符串拼接 只有在6-7个或更多的连接完成时,时间和内存消耗才会更有效 strings .

    不良实践用法:

    StringBuilder myString = new StringBuilder("123");
    myString.Append("234");
    myString.Append("345");
    

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

    StringBuilder myString = new StringBuilder("123");
    if (Console.ReadLine() == "a")
    {
        myString.Append("234");
    }
    myString.Append("345");
    

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

    StringBuilder myString = new StringBuilder("123");
    while (Console.ReadLine() == "a")
    {
        myString.Append("234"); //Average loop times 4~ or more
    }
    myString.Append("345");
    
        2
  •  13
  •   Tamir Vered    8 年前

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

    所以当你写 result += a; 你有三个分开的 在存储器中: a ,的旧值 result 以及新值。当然,如果只连接有限数量的 。如果你在 for 循环在大型集合上迭代可能会成为问题。

    这个 StringBuilder 类在这些情况下提供了改进的性能。而不是创建新的 为了存储连接的结果,它使用相同的对象。所以如果你使用 stringBuilder.Append(a); 你永远不会有“旧值 后果 ".


    当然,这种内存效率是有代价的。当仅连接少量 字符串拼接 在速度方面通常效率较低,因为与不可变的相比,它有更多的开销 一串


    需要记住的一点是,当您需要中间字符串时 字符串拼接 由于调用 .ToString() 在其上创建 一串 .

        3
  •  3
  •   Tamir Vered    8 年前

    原因是因为 strings 是不可变的。连接 string 创建一个新的 一串 。因此,当您需要连接多个 你创造了很多 objects 。这在内存方面花费不多,因为每个 一串 使用一次。但它确实为 GC .

    StringBuilder 但是使用相同的 object 但这样做是以易用性为代价的。