代码之家  ›  专栏  ›  技术社区  ›  David Espart

清除.NET StringBuilder内容的最佳方法

  •  67
  • David Espart  · 技术社区  · 15 年前

    我想问一下您认为清除内容以便重用StringBuilder的最佳方法(持续时间少/消耗资源少)。想象一下下面的场景:

    StringBuilder sb = new StringBuilder();
    foreach(var whatever in whateverlist)
    {
      sb.Append("{0}", whatever);
    }
    
    //Perform some stuff with sb
    
    //Clear stringbuilder here
    
    //Populate stringbuilder again to perform more actions
    foreach(var whatever2 in whateverlist2)
    {
      sb.Append("{0}", whatever2);
    }
    

    当清除StringBuilder时,我可以考虑两种可能性:

    sb = new StringBuilder();
    

    sb.Length = 0;
    

    最好的清理方法是什么?为什么?

    谢谢您。

    编辑:当前.NET 3.5版本。

    10 回复  |  直到 6 年前
        1
  •  64
  •   Mike Hofer    15 年前

    如果在.NET 2.0或3.5中执行此操作,请编写一个扩展方法,如下所示:

    /// <summary>
    ///     Clears the contents of the string builder.
    /// </summary>
    /// <param name="value">
    ///     The <see cref="StringBuilder"/> to clear.
    /// </param>
    public static void Clear(this StringBuilder value)
    {
        value.Length = 0;
        value.Capacity = 0;
    }
    

    然后,您可以这样清除它:

    someStringBuilder.Clear();
    

    然后,当4.0出现时,您可以放弃扩展方法而选择4.0版本。

    更新 :将容量设置为零可能不是个好主意。如果重用同一个实例,这将保证在附加到生成器时重新分配。但是,在将容量设置为非常小的值(如1)之前,不会释放生成器实例中的内存。Capacity属性的默认值为16。您可能需要考虑使用16,或者(尽管效率较低)将容量设置两次:

    • 设置为1或0以清除内存
    • 将其设置为原始容量值(可能与16不同)以恢复它。
        2
  •  28
  •   GraemeF    15 年前

    在.NET 4.0中,您可以调用 sb.Clear() 但在旧版本中,您应该设置 sb.Length = 0 .

    这个 Clear() 方法已添加到.NET 4.0中。

        3
  •  15
  •   Paul Sonier    15 年前

    创建新的StringBuilder。旧的方法维护与之相关联的资源(例如,最大长度的缓冲区),这些资源最好只是被垃圾收集掉。

        4
  •  10
  •   Earlz    15 年前

    我认为你在做过早的优化。

    我敢打赌 sb.Length=0; 最快的方法是避免创建另一个对象,并将另一个对象放在一边,以供GC最终收集。

    我认为创建一个新的StringBuilder是解决内存问题的最佳途径。和设置 sb.Length 对于速度问题来说是最好的选择。

        5
  •  10
  •   bdukes Jon Skeet    15 年前

    从上的社区内容 MSDN :

    有效清除 不破坏它的StringBuilder 用途:

     someStringBuilder.length = 0;
     someStringBuilder.capacity = 0;
    

    这会破坏它的内容和 将其大小调整为零。如上所述 清楚尺寸会影响较小 应用。

        6
  •  5
  •   Dave Clemmer manu    12 年前

    在.NET框架中,引入了4种新方法 StringBuilder 班级。方法名为“clear”。此方法帮助您清除或删除 字符串拼接 物体。

    下面是这个例子。

        System.Text.StringBuilder objSB = new System.Text.StringBuilder();
        //Append values
        objSB.Append("This is .Net Blog.");
        objSB.Append("You can get latest C# Tips over here.");
    
        //Display on screen
        Response.Write(objSB.ToString());
        Response.Write("<br/><br/>");
    
        //Clear object using Clear method
        objSB.Clear();
    
        //Append another values
        objSB.Append("This blog is very useful for .Net Beginners");
    
        Response.Write("After Clear<br/><br/>");
        //Display on screen
        Response.Write(objSB.ToString());
    
        7
  •  2
  •   Kim R    15 年前

    如果您希望减少内存使用,我将使用clr profiler,使用上面其他人描述的方法,检查StringBuilder对象在其生命周期中使用的内存量。然后,您可以满足自己,您选择的选项适合您的需求,并释放您需要的资源。

        8
  •  1
  •   Matt Grande    15 年前

    我想最好的清理方法是使用 sb = new StringBuilder(); . 也就是说,我认为如果您一起创建一个新的字符串生成器对象会更好。

    编辑

    我希望这是最好的解决办法。

    public StringBuilder MakeString(IEnumerable<CoolType> list)
    {
        StringBuilder sb = new StringBuilder();
    
        foreach(var whatever in list)
        {
            sb.Append("{0}", whatever);
        }
    }
    
    var sb = MakeString(whateverList);
    // Do stuff
    // Clear stuff
    sb = MakeString(whateverList2);
    
        9
  •  0
  •   Max CHien    6 年前

    只需调用clear()方法,只需设置长度=0, 如果我们想保存内存,也可以将容量设置为0

    public StringBuilder Clear() {
            this.Length = 0;
            return this;
     }
    

    参考文献:在 referencesource.microsoft.com

        10
  •  0
  •   PJJ    6 年前
    // P.S. to be ultra efficient 
    // make a good guess at the initial allocation too !!!!
    int PerWhatever_SizeEstimate = 4; // a guess of average length... you known your data
    StringBuilder sb = new StringBuilder( whateverlist.Length * PerWhatever_SizeEstimate);
    
    // reallocation needed? 
    // if you want to be efficient speed and memory wise... 
    sb.Length = 0;  // rest internal index but don't release/resize memory
    // if a ...BIG... difference in size
    if( whatever2.Length < whatever.Length * 2/3  
     || whatever2.Length > whatever.Length * 1.5)
    {
        //scale capacity appropriately
        sb.Capaciy = sb.Capacity * whatever2.Length / whatever.Length;
    }