web-dev-qa-db-fra.com

meilleur moyen d'effacer le contenu de StringBuilder .NET

Je voudrais demander quel est, à votre avis, le meilleur moyen (dure moins/consomme moins de ressources) d’effacer le contenu afin de pouvoir réutiliser un StringBuilder. Imaginez le scénario suivant:

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

Et lorsque je supprime StringBuilder, je peux penser à deux possibilités:

sb = new StringBuilder();

ou

sb.Length = 0;

Quel est le meilleur moyen de le nettoyer et pourquoi? 

Je vous remercie.

EDIT: J'utilise la version actuelle .NET 3.5.

67
David Espart

Si vous faites cela dans .NET 2.0 ou 3.5, écrivez une méthode d'extension pour le faire comme ceci:

/// <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;
}

Ensuite, vous pouvez le nettoyer comme ceci:

someStringBuilder.Clear();

Ensuite, lorsque la version 4.0 sera disponible, vous pourrez abandonner votre méthode d’extension au profit de la version 4.0.

UPDATE: Ce n'est probablement pas une bonne idée de définir la capacité à zéro. Cela garantira des réaffectations lors de l'ajout au générateur, si vous réutilisez la même instance. Toutefois, la mémoire dans l'instance du générateur n'est pas libérée tant que vous n'avez pas défini la capacité à une valeur très petite (telle que 1). La valeur par défaut de la propriété Capacity est 16. Vous pouvez envisager d'utiliser 16, ou (bien que ce soit moins efficace) de définir la capacité deux fois: 

  • Réglez-le sur 1 ou zéro pour effacer la mémoire
  • Définissez-le sur votre valeur de capacité d'origine (qui peut différer de 16) pour la restaurer.
64
Mike Hofer

Dans .NET 4.0, vous pouvez appeler sb.Clear(), mais dans les anciennes versions, vous devez définir sb.Length = 0.

La méthode Clear() a été ajoutée dans .NET 4.0.

28
GraemeF

Créez le nouveau StringBuilder. L'ancien conserve les ressources qui lui sont associées (tampon de longueur maximale, par exemple) et qui sont préférables.

15
Paul Sonier

Je pense que vous faites l'optimisation prématurée.

Je parierais que faire sb.Length=0; serait le plus rapide à éviter de créer un autre objet et de mettre un autre objet de côté pour que GC puisse éventuellement le collecter. 

Je pense que créer un nouveau StringBuilder serait le meilleur moyen de résoudre les problèmes de mémoire. et régler sb.Length serait la meilleure solution pour les problèmes de vitesse. 

10
Earlz

Du contenu de la communauté sur MSDN :

Pour effacer efficacement votre constructeur de chaînes sans le détruire utilisation:

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

Cela détruit à la fois son contenu et le redimensionne à zéro. Comme indiqué ci-dessus effacer la taille peut avoir un impact plus petit applications.

10
Yuriy Faktorovich

Dans .NET Framework 4, de nouvelles méthodes ont été introduites dans la classe StringBuilder. Le nom de la méthode est "Clear". Cette méthode vous aide à effacer ou à supprimer des valeurs ou des données d'objets StringBuilder.

Voici un exemple pour cela.

    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
Jayesh Sorathia

Si vous cherchez à réduire l'utilisation de la mémoire, j'utiliserais le profileur CLR pour vérifier la quantité de mémoire utilisée par les objets StringBuilder tout au long de leur cycle de vie, à l'aide des méthodes décrites par d'autres personnes. Ensuite, vous pouvez vous assurer que l’option que vous choisissez est adaptée à vos besoins et libère les ressources dont vous avez besoin.

2
Kim R

Je dirais que la meilleure façon de résoudre ce problème est d'utiliser sb = new StringBuilder();. Cela étant dit, je pense que ce serait encore mieux si vous créiez un nouvel objet constructeur de chaînes.

MODIFIER

J'espère que cela va sans dire que c'est la meilleure solution.

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);
1
Matt Grande
// 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;
}
0
PJJ

C # en résumé Pour effacer le contenu d'une StringBuilder, il existe deux méthodes:

  1. Définissez sa Length sur zéro:

    Définir la variable Length de StringBuilder sur zero ne réduit pas sa capacité interne. Ainsi, si StringBuilder contenait auparavant un million de caractères, il continuera à occuper environ 2 Mo de mémoire après la remise à zéro de sa longueur.

  2. Instancier un nouveau:

    Si vous souhaitez release the memory, vous devez créer un nouveau StringBuilder et permettre à l'ancien de disparaître de la portée (et d'être récupéré), avec cette approche, vous pouvez résoudre le problème de l'élément précédent.

0
Sina Lotfi

Appelez simplement la méthode Clear () en définissant simplement length = 0, Nous pouvons également définir Capacity = 0 si nous voulons économiser de la mémoire.

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

Ref: In referencesource.Microsoft.com

0
MaxJ