web-dev-qa-db-fra.com

StringBuilder.Append Vs StringBuilder.AppendFormat

Je me posais des questions sur StringBuilder et j'ai une question que j'espérais que la communauté serait en mesure de l'expliquer.

Oublions simplement la lisibilité du code, laquelle est plus rapide et pourquoi?

StringBuilder.Append:

StringBuilder sb = new StringBuilder();
sb.Append(string1);
sb.Append("----");
sb.Append(string2);

StringBuilder.AppendFormat:

StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}----{1}",string1,string2);
36
Sergio

Il est impossible de dire, ne connaissant pas la taille de string1 et string2

Avec l'appel à AppendFormat , il préallouera le tampon une seule fois, en fonction de la longueur de la chaîne de formatage et des chaînes à insérer, puis tout concaténer et l'insérer dans le tampon. Pour les très grandes chaînes, cela sera avantageux par rapport aux appels séparés à Append , ce qui pourrait entraîner le développement de la mémoire tampon plusieurs fois.

Cependant, les trois appels à Append peuvent ou non déclencher une croissance de la mémoire tampon et cette vérification est effectuée à chaque appel. Si les chaînes sont suffisamment petites et qu'aucune expansion de mémoire tampon n'est déclenchée, le processus sera plus rapide que l'appel à AppendFormat car il ne sera pas nécessaire d'analyser la chaîne de format pour déterminer où effectuer les remplacements.

Plus de données sont nécessaires pour une réponse définitive

Il convient de noter qu’il est peu question d’utiliser la méthode static Concat SUR LA CLASSE String ( La réponse de Jon using AppendWithCapacity m’a rappelé cela). Les résultats de ses tests montrent que c'est le meilleur des cas (en supposant que vous n'avez pas à tirer parti d'un spécificateur de format spécifique). String.Concat fait la même chose en ce sens qu'il prédétermine la longueur des chaînes à concaténer et préallouer le tampon (avec un peu plus de temps système dû aux constructions en boucle dans les paramètres). Ses performances seront comparables à la méthode AppendWithCapacity de Jon.

Ou simplement l'opérateur d'ajout brut, puisqu'il compile un appel à String.Concat de toute façon, avec l'avertissement que tous les ajouts sont dans la même expression:

// One call to String.Concat.
string result = a + b + c;

NE PAS

// Two calls to String.Concat.
string result = a + b;
result = result + c;

Pour tous ceux qui mettent en place le code de test

Vous devez exécuter vos scénarios de test dans des exécutions distinctes (ou au moins, effectuer un GC entre les mesures de tests distincts). La raison en est que si vous dites que 1 000 000 de tests sont créés, créant un nouveau StringBuilder à chaque itération de la boucle pour un test, puis vous exécutez le test suivant qui boucle le même nombre de fois, créant ainsi un supplémentaire 1 000 000 StringBuilder instances, le GC interviendra très probablement lors du deuxième test et en empêchera le chronométrage.

40
casperOne

casperOne est correct . Une fois que vous atteignez un certain seuil, la méthode Append() devient plus lente que AppendFormat(). Voici les différentes longueurs et les ticks écoulés de 100 000 itérations de chaque méthode:

Longueur: 1

Append()       - 50900
AppendFormat() - 126826

Longueur: 1000

Append()       - 1241938
AppendFormat() - 1337396

Longueur: 10.000

Append()       - 12482051
AppendFormat() - 12740862

Longueur: 20 000

Append()       - 61029875
AppendFormat() - 60483914

Lorsque des chaînes d'une longueur proche de 20 000 sont introduites, la fonction AppendFormat() va légèrement surpasser Append().

Pourquoi cela arrive-t-il? Voir Réponse de casperOne .

Modifier:

Je répète chaque test individuellement sous Configuration de la version et mets à jour les résultats.

22
John Rasch

Append sera plus rapide dans la plupart des cas car il existe de nombreuses surcharges dans cette méthode qui permettent au compilateur d'appeler la bonne méthode. Puisque vous utilisez Strings, StringBuilder peut utiliser la surcharge String pour Append

AppendFormat prend une String puis un Object[], ce qui signifie que le format devra être analysé et que chaque Object du tableau devra être ToString'd avant de pouvoir être ajouté au tableau interne StringBuilder's.

Note: Au point de casperOne - il est difficile de donner une réponse exacte sans plus de données.

5
Andrew Hare

StringBuilder a également ajouté en cascade: Append() renvoie la StringBuilder elle-même, vous pouvez donc écrire votre code comme suit:

StringBuilder sb = new StringBuilder();
sb.Append(string1)
  .Append("----")
  .Append(string2);

Propre et génère moins de code IL (bien que ce soit vraiment une micro-optimisation).

2
Tommy Carlier

Bien sûr profilez pour savoir à coup sûr dans chaque cas.

Cela dit, je pense que ce sera généralement le premier car vous n'analyserez pas la chaîne de format à plusieurs reprises.

Cependant, la différence serait très petite. Au point que vous devriez vraiment envisager d'utiliser AppendFormat dans la plupart des cas de toute façon.

1
Joel Coehoorn

Je suppose que c'est l'appel qui a fait le moins de travail. Append ne fait que concaténer des chaînes, où AppendFormat effectue des substitutions de chaînes. Bien sûr, ces jours-ci, on ne peut jamais dire ...

0
Paul W Homer

1 devrait être plus rapide car il s'agit simplement d'ajouter des chaînes alors que 2 doit créer une chaîne basée sur un format, puis l'ajouter. Donc, il y a un pas supplémentaire là-dedans.

0
Micah

Plus rapide est 1 dans votre cas, mais ce n'est pas une comparaison juste. Vous devez demander à StringBuilder.AppendFormat () vs StringBuilder.Append (string.Format ()) - où le premier est plus rapide en raison du travail interne avec le tableau de caractères.

Votre deuxième option est plus lisible cependant.

0
Miha Markic