Quand utiliser StringBuilder?
-
22-07-2019 - |
Question
Je comprends les avantages de StringBuilder.
Mais si je veux concaténer 2 chaînes, alors je suppose qu'il est préférable (plus rapide) de le faire sans StringBuilder. Est-ce correct?
À quel moment (nombre de chaînes) devient-il préférable d'utiliser StringBuilder?
La solution
Je vous suggère vivement de lire La triste tragédie du théâtre de la micro-optimisation . , de Jeff Atwood.
Il s'agit de la concaténation simple, de StringBuilder et d'autres méthodes.
Maintenant, si vous voulez voir des chiffres et des graphiques, suivez le lien;)
Autres conseils
Mais si je veux concatiner 2 cordes, alors je suppose que c'est mieux (plus vite) de le faire sans StringBuilder. Est-ce correct?
C’est vrai, vous pouvez trouver pourquoi exactement expliqué très bien sur:
http://www.yoda.arachsys.com/csharp/stringbuilder.html
Résumé: si vous pouvez concatiner des chaînes en une fois, comme
var result = a + " " + b + " " + c + ..
mieux vaut sans StringBuilder, car la copie est créée (la longueur de la chaîne résultante est calculée à l'avance.);
Pour une structure comme
var result = a;
result += " ";
result += b;
result += " ";
result += c;
..
de nouveaux objets sont créés à chaque fois, vous devez donc considérer StringBuilder.
À la fin, l'article résume ces règles empiriques:
Règles du pouce
Alors, quand devriez-vous utiliser StringBuilder, et quand devriez-vous utiliser la chaîne opérateurs de concaténation?
Utilisez certainement StringBuilder lorsque vous concaténer dans un non-trivial boucle - surtout si vous ne savez pas bien sûr (au moment de la compilation) combien itérations que vous ferez à travers le boucle. Par exemple, lire un fichier une caractère à la fois, construisant un chaîne que vous allez en utilisant l'opérateur + = est potentiellement suicide performance.
Utilisez certainement la concaténation opérateur quand vous le pouvez (lisiblement) spécifier tout ce qui doit être concaténé dans une déclaration. (Si vous avoir un éventail de choses à concaténer, envisager d'appeler String.Concat explicitement - ou String.Join si vous avez besoin d'un délimiteur.)
N'ayez pas peur de séparer les littéraux en plusieurs bits concaténés - le le résultat sera le même. Vous pouvez aider lisibilité en cassant un long littéral en plusieurs lignes, par exemple, avec aucun mal à la performance.
Si vous avez besoin des résultats intermédiaires de la concaténation pour quelque chose autre que de nourrir la prochaine itération de concaténation, StringBuilder n'est pas va vous aider. Par exemple, si vous construisez un nom complet à partir d'une première nom et un nom de famille, puis ajoutez un troisième information (la surnom, peut-être) jusqu'à la fin, vous aurez seulement profiter de l'utilisation de StringBuilder si vous n’avez pas besoin du (prénom + nom de famille) chaîne à une autre fin (comme nous le faisons dans l'exemple qui crée un objet Personne).
Si vous n'avez que quelques concaténations faire, et vous voulez vraiment les faire dans des déclarations séparées, il ne vraiment important dans quel sens vous allez. Lequel manière est plus efficace dépendra de le nombre de concaténations les tailles de chaîne impliqué, et quel ordre ils sont concaténés. Si vous avez vraiment croire que ce morceau de code soit un goulot d'étranglement, profil ou comparer les résultats dans les deux sens.
System.String est un objet immuable. Cela signifie que chaque fois que vous modifiez son contenu, une nouvelle chaîne est allouée, ce qui prend du temps (et de la mémoire?). En utilisant StringBuilder, vous modifiez le contenu réel de l'objet sans en allouer un nouveau.
Utilisez donc StringBuilder lorsque vous devez apporter de nombreuses modifications à la chaîne.
Pas vraiment ... vous devriez utiliser StringBuilder si vous concaténez des chaînes volumineuses ou si vous avez plusieurs concaténations, comme dans une boucle.
Il n'y a pas de réponse définitive, seulement des règles empiriques. Mes règles personnelles ressemblent à ceci:
- Si vous concaténez dans une boucle, utilisez toujours un
StringBuilder
. - Si les chaînes sont grandes, utilisez toujours un
StringBuilder
. - Si le code de concaténation est ordonné et lisible à l'écran, c'est que tout va bien.
Si ce n'est pas le cas, utilisez unStringBuilder
.
Pour paraphraser
Alors tu compteras jusqu'à trois, pas plus, pas moins. Tu compteras trois, et le décompte sera trois. Vous ne comptez pas quatre personnes, vous ne comptez pas non plus deux, sauf que vous passez ensuite à trois. Une fois que le nombre trois, étant le troisième, soit atteint, alors tu lobbest ta Sainte Grenade d'Antioche
J'utilise généralement le constructeur de chaînes pour tout bloc de code qui entraînerait la concaténation de trois chaînes ou plus.
- Si vous concaténez des chaînes dans une boucle, envisagez d'utiliser StringBuilder au lieu de String .
- Dans le cas d'une concaténation simple, il est possible que vous ne voyiez pas du tout la différence de temps d'exécution
Voici une application de test simple pour prouver le point:
class Program
{
static void Main(string[] args)
{
const int testLength = 30000;
var StartTime = DateTime.Now;
//TEST 1 - String
StartTime = DateTime.Now;
String tString = "test string";
for (int i = 0; i < testLength; i++)
{
tString += i.ToString();
}
Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString());
//result: 2000 ms
//TEST 2 - StringBuilder
StartTime = DateTime.Now;
StringBuilder tSB = new StringBuilder("test string");
for (int i = 0; i < testLength; i++)
{
tSB.Append(i.ToString());
}
Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString());
//result: 4 ms
Console.ReadLine();
}
}
Résultats:
-
30'000 itérations
- Chaîne - 2000 ms
- StringBuilder - 4 ms
-
1000 itérations
- Chaîne - 2 ms
- StringBuilder - 1 ms
-
500 itérations
- Chaîne - 0 ms
- StringBuilder - 0 ms
Mais si je veux concaténer 2 chaînes, alors je suppose qu'il est préférable et plus rapide de le faire sans StringBuilder. Est-ce correct?
Oui. Mais plus important encore, il est beaucoup plus lisible d’utiliser une String
vanilla dans de telles situations. En revanche, son utilisation en boucle est logique et peut être aussi lisible qu'une concaténation.
Je me méfierais des règles empiriques qui citent des nombres spécifiques de concaténation comme seuil. Son utilisation dans des boucles (et uniquement des boucles) est probablement tout aussi utile, plus facile à mémoriser et plus logique.
Tant que vous pouvez taper physiquement le nombre de concaténations (a + b + c ...), cela ne devrait pas faire grande différence. N carré (à N = 10) correspond à un ralentissement de 100X, ce qui ne devrait pas être trop grave.
Le gros problème est que vous concaténez des centaines de chaînes. À N = 100, vous obtenez un ralentissement de 10 000 fois. Ce qui est assez mauvais.
Je ne pense pas qu'il y ait une ligne de démarcation entre quand utiliser ou pas. À moins bien sûr que quelqu'un ait effectué des tests approfondis pour déterminer les conditions idéales.
Pour moi, je n'utiliserai pas StringBuilder si je concatène simplement deux énormes chaînes. S'il y a une boucle avec un compte indéterministe, je le ferai probablement, même si la boucle est petite.
Une simple concaténation ne vaut pas l'utilisation d'un StringBuilder. J'ai généralement utilisé 5 concaténations en règle générale.
La classe StringBuilder fournit au développeur un ensemble de méthodes permettant de manipuler une chaîne de caractères mutable. Elle peut être utilisée lorsque vous souhaitez modifier une chaîne sans créer de nouvel objet. le problème de surcharge ou de goulot d'étranglement de la concaténation de chaînes normale.
L'utilisation de la classe StringBuilder peut améliorer les performances lors de la concaténation de plusieurs chaînes dans une boucle.
Voici une liste de quelques opérations pouvant être effectuées pour manipuler une chaîne à l'aide de la classe StringBuilder dans .NET
Ajouter : ajoute des informations à la fin du constructeur de chaînes en cours.
AppendFormat : remplace un spécificateur de format transmis dans une chaîne par du texte mis en forme.
Insérer : insère une chaîne ou un objet dans l'index spécifié du StringBuilder actuel.
Supprimer : supprime un nombre spécifié de caractères du constructeur de chaînes actuel.
Remplacer : remplace un caractère spécifié à un index spécifié.