web-dev-qa-db-fra.com

Comment utiliser judicieusement StringBuilder?

Je suis un peu confus quant à l’utilisation de StringBuilder class, d’abord:

Une opération de concaténation d'objet string crée toujours un nouvel objet à partir de string existant et des nouvelles données. Un objet StringBuilder maintient un tampon pour permettre la concaténation de nouvelles données. Les nouvelles données sont ajoutées à la fin de la mémoire tampon si de la place est disponible; sinon, un nouveau tampon plus grand est alloué, les données du tampon d'origine sont copiées dans le nouveau tampon, puis les nouvelles données sont ajoutées au nouveau tampon.

Mais à quoi sert-il de créer StringBuilder instance pour éviter de créer une nouvelle instance de String? Cela ressemble à un échange "un pour un".

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

Pourquoi je ne devrais pas simplement utiliser

+=

Edit: Ok, je sais maintenant comment réutiliser une instance de StringBuilder (je ne sais toujours pas si cela est correct avec les normes de code), mais cela ne vaut pas la peine d'être utilisé avec un seul string, n'est-ce pas?

63

Modifier immuable des structures telles que string s doit être fait en copiant la structure et en consommant plus de mémoire et ralentir le temps d'exécution de l'application (augmentant également le temps GC, etc ...).

StringBuilder vient résoudre ce problème en utilisant le même objet mutable pour les manipulations.

Cependant:

lors de la concaténation de string au moment de la compilation, comme suit:

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

il va en fait compiler quelque chose comme ça:

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

cette fonction est plus rapide que de travailler avec StringBuilder pour le nombre de strings entrant dans la fonction est connue.

donc, pour les concaténations string connues au moment de la compilation, vous devriez préférer string.Concat().

comme pour un nombre inconnu de string comme dans le cas suivant:

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

Maintenant, le compilateur ne peut pas utiliser la fonction string.Concat(), cependant, StringBuilder semble être plus efficace en termes de consommation de temps et de mémoire uniquement lorsque la concaténation est effectuée à 6-7 ou plus strings.

Mauvais usage pratique:

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

Utilisation pratique fine (notez que if est utilisé):

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

Utilisation recommandée (notez que la boucle while est utilisée):

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

Un string est un classe immuable. Vous ne pouvez pas le modifier, créez seulement un nouveau strings.

Ainsi, lorsque vous écrivez result += a;, Vous avez trois strings en mémoire à cet endroit: a, l'ancienne valeur de result et la nouvelle valeur. Bien sûr, c'est parfait si vous ne concaténez qu'un nombre limité de strings. Si vous faites cela dans une boucle for itérant une grande collection, cela peut devenir un problème.

La classe StringBuilder offre de meilleures performances dans ces cas. Au lieu de créer un nouveau strings pour stocker le résultat de la concaténation, il utilise le même objet. Donc, si vous utilisez stringBuilder.Append(a);, vous n’aurez jamais l’équivalent de "l'ancienne valeur de result".


Cette efficacité de la mémoire a un prix bien sûr. Lorsque vous concaténez seulement un petit nombre de strings un StringBuilder est souvent moins efficace en termes de rapidité, car il y avait plus de temps système par rapport à la classe immuable string.


Une chose à garder à l'esprit est que lorsque vous avez besoin des chaînes intermédiaires, alors StringBuilder peut devenir moins efficace, car appeler .ToString() crée une nouvelle copie de string.

12
Dirk

La raison en est que strings sont immuables. Lors de la concaténation d'un string, vous créez un nouveau string. Ainsi, lorsque vous devez concaténer plusieurs strings, vous créez beaucoup de objects. Cela ne coûte pas cher en termes de mémoire, car chaque string est utilisé une fois. Mais cela donne du travail supplémentaire pour le GC.

StringBuilder utilise cependant le même object à chaque fois, mais au détriment de la facilité d'utilisation.

1
Aron