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


75

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


4
不是答案,而是有趣的阅读内容:bobondevelopment.com/2007/06/11/…–
菲利普·华莱士

1
不包括StringBuilder.Clear()方法作为替代方法的原因是什么?
符文FS

@Rune:c#4.0尚未发布,仅适用于4.0。在MSDN上说:在以下
位置

对我来说很幸运,C#4.0出了blogs.msdn.com/somasegar/default.aspx
Rune FS 2010年

2
我想知道为什么Length可写,但是没有读写属性“ Text”?他说sb.Text = "";,似乎更清楚的是sb.Length = 0;,和Text财产也将在常见的场景,其中一个原本不得不说的帮助sb.Length = 0; sb.Append(StuffToStartWith);
2012年

Answers:


72

如果您是在.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版本。

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

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

整洁的方法。正是我想要的。
阿比

15
我建议不要清除容量,除非StringBuilder已知的容量过大。特别是在.net的早期版本中,如果将重复构建超过42,500个字符的字符串,则在每个字符串之后清除缓冲区将导致每次必须重新增长缓冲区时,才在大对象堆中分配额外的对象。那是一件坏事。
2012年

2
将容量设置为0是一个有趣的想法。仅使用清除或将长度设置为0时,重复使用Insert()可能会发生内存泄漏,因为尽管清除了,但容量仍在不断增长。(见我的问题:stackoverflow.com/questions/29574469/...
彼得·胡贝尔

29

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

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


15
如果要重用它,是否不希望重用缓冲区?
GraemeF,2009年

2
取决于第一次创建的字符串与第二次创建的字符串相比的大小差异。或者至少我会这样认为
Earlz

16

创建新的StringBuilder。旧的资源会维护与其相关的资源(例如,最大长度的缓冲区),最好是将其垃圾回收掉。


11

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

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

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


11

MSDN上的社区内容:

要有效清除您的stringbuilder而不破坏它,请使用:

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

这将破坏其内容并将其大小调整为零。如上所述,清除大小可能会影响较小的应用程序。


5

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

2

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


1

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

5
sb = new StringBuilder()正在制作一个新的字符串生成器对象。
菲利普·华莱士

这样做确实会创建一个新的字符串构建器对象。
保罗·索尼尔

我认为Matt的意思是为new声明一个新变量StringBuilder
陶涛

抱歉,要弄清楚我建议做这样的事情:var wellNamedStringBuilder = new StringBuilder();
马特·格兰德,

1

C#概述要清除a的内容StringBuilder,有两种方法:

  1. 将其Length设置为零:

    设置一个StringBuilder是Lengthzero不收缩其内部能力。因此,如果StringBuilder以前包含一百万个字符,则将其Length设置为零后,它将继续占据大约2 MB的内存。

  2. 实例化一个新的:

    如果愿意release the memory,您必须创建一个新的StringBuilder并允许旧的StringBuilder退出作用域(并进行垃圾回收),使用这种方法可以解决上一个项目的问题。


0

只需调用Clear()方法,只需将length设置为0即可,如果要节省内存,也可以将Capacity设置为0。

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

参考:在referencesource.microsoft.com中


0
// 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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.