【问题标题】:best way to clear contents of .NET's StringBuilder清除 .NET 的 StringBuilder 内容的最佳方法
【发布时间】:2010-12-15 03:11:50
【问题描述】:

我想问一下您认为清除内容以重用 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 版本。

【问题讨论】:

  • 不是答案,但读起来很有趣:bobondevelopment.com/2007/06/11/…
  • 不包括 StringBuilder.Clear() 方法作为替代方法的原因是什么?
  • @Rune: c# 4.0 还没有出来,它只有 4.0。在 MSDN 上它说:支持:4。
  • 我很幸运,c#4.0 已经发布了blogs.msdn.com/somasegar/default.aspx
  • 我想知道为什么Length 是可写的,但没有读/写“文本”属性?说sb.Text = ""; 似乎比sb.Length = 0; 更清楚,而Text 属性也有助于在否则必须说sb.Length = 0; sb.Append(StuffToStartWith); 的常见情况下。

标签: c# .net optimization .net-3.5


【解决方案1】:

C# In A Nutshell清除StringBuilder的内容,有两种方法:

  1. 将其Length 设置为零:

    将 StringBuilder 的 Length 设置为 zero 不会缩小其内部容量。因此,如果 StringBuilder 之前包含一百万个字符,那么在将其 Length 归零后,它将继续占用大约 2 MB 的内存。

  2. 实例化一个新的:

    如果你想release the memory,你必须创建一个新的StringBuilder并允许旧的退出范围(并被垃圾收集),通过这种方法你可以解决上一个项目的问题。

【讨论】:

    【解决方案2】:
    // 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;
    }
    

    【讨论】:

      【解决方案3】:

      只需调用 Clear() 方法只需设置 length = 0 , 如果我们想节省内存,我们也可以设置Capacity = 0

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

      参考:referencesource.microsoft.com

      【讨论】:

        【解决方案4】:

        在 .NET Framework 4 中,StringBuilder 类中引入了新方法。方法名称是“清除”。此方法可帮助您清除或删除 StringBuilder 对象中的值或数据。

        这是一个例子。

            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());
        

        【讨论】:

          【解决方案5】:

          如果您在 .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)之前,不会释放构建器实例中的内存。容量属性的默认值为 16。您可能需要考虑使用 16,或者(尽管效率较低)将容量设置两次:

          • 将其设置为 1 或零以清除内存
          • 将其设置为原始容量值(可能不同于 16)以恢复它。

          【讨论】:

          • 简洁的方法。正是我想要的。
          • 我建议不要清除容量,除非已知 StringBuilder 拥有异常大的东西。尤其是在早期版本的 .net 中,如果要重复构建超过 42,500 个字符的字符串,则在每个字符串之后清除缓冲区将导致每次缓冲区必须重新增长时在大对象堆中分配额外的对象。这是一件坏事。
          • 将容量设置为 0 是一个有趣的想法。仅使用 Clear 或仅将长度设置为 0 时,重复使用 Insert() 时可能会发生内存泄漏,因为尽管使用了 Clear,Capacity 仍会不断增长。 (见我的问题:stackoverflow.com/questions/29574469/…
          【解决方案6】:

          如果您希望减少内存使用量,我会使用 CLR Profiler 来检查您的 StringBuilder 对象在其生命周期中使用了多少内存,方法是使用其他人在上面描述的方法。然后,您可以让自己确信您选择的选项适合您的需求,并且正在释放您需要的资源。

          【讨论】:

            【解决方案7】:

            我想说清除它的最好方法是使用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);
            

            【讨论】:

            • sb = new StringBuilder() 正在创建一个新的字符串生成器对象。
            • 这样做确实会创建一个新的字符串生成器对象。
            • 我认为马特的意思是为新的StringBuilder 声明一个新变量。
            • 抱歉,澄清一下,我建议您这样做:var wellNamedStringBuilder = new StringBuilder();
            【解决方案8】:

            来自MSDN上的社区内容:

            有效清除您的 stringbuilder 不破坏它 使用:

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

            这会破坏其内容和 将其大小调整为零。如上所述 清除尺寸会影响更小 应用程序。

            【讨论】:

              【解决方案9】:

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

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

              我认为创建一个新的 StringBuilder 将是解决内存问题的最佳方法。设置sb.Length 将是解决速度问题的最佳选择..

              【讨论】:

                【解决方案10】:

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

                Clear() 方法是在 .NET 4.0 中添加的。

                【讨论】:

                • 如果你重用它,你不想重用缓冲区吗?
                • 取决于第一次创建的字符串与第二次创建的字符串相比有多大的差异。或者至少我会这么认为
                【解决方案11】:

                创建新的 StringBuilder。旧的维护与它相关的资源(例如,最大长度的缓冲区),最好只是将其作为垃圾收集起来。

                【讨论】:

                  猜你喜欢
                  • 2010-11-13
                  • 2011-08-06
                  • 2011-08-16
                  • 1970-01-01
                  • 2019-10-21
                  • 2015-07-23
                  • 2015-07-10
                  • 1970-01-01
                  相关资源
                  最近更新 更多