web-dev-qa-db-fra.com

StringBuilder: comment obtenir la chaîne finale?

Quelqu'un m'a dit qu'il était plus rapide de concaténer des chaînes avec StringBuilder. J'ai changé mon code mais je ne vois aucune propriété ou méthode pour obtenir la chaîne de construction finale.

Comment puis-je obtenir la chaîne?

57
Mister Dev

Vous pouvez utiliser .ToString() pour obtenir le String du StringBuilder.

110
Patrick Desjardins

Lorsque vous dites "il est plus rapide de concaténer String avec un générateur de chaîne", cela n'est vrai que si vous êtes à plusieurs reprises (je répète - à plusieurs reprises ) concaténation au même objet.

Si vous concaténez simplement 2 chaînes et faites immédiatement quelque chose avec le résultat en tant que string, il n'y a aucun intérêt à utiliser StringBuilder.

Je suis juste tombé sur l'écriture de Nice de Jon Skeet: http://www.yoda.arachsys.com/csharp/stringbuilder.html

Si vous utilisez StringBuilder, pour obtenir le string résultant, il suffit d'appeler ToString() (sans surprise).

13
Michael Burr

Une fois que vous avez terminé le traitement à l'aide de StringBuilder, utilisez la méthode ToString pour renvoyer le résultat final.

Depuis MSDN:

using System;
using System.Text;

public sealed class App 
{
    static void Main() 
    {
        // Create a StringBuilder that expects to hold 50 characters.
        // Initialize the StringBuilder with "ABC".
        StringBuilder sb = new StringBuilder("ABC", 50);

        // Append three characters (D, E, and F) to the end of the StringBuilder.
        sb.Append(new char[] { 'D', 'E', 'F' });

        // Append a format string to the end of the StringBuilder.
        sb.AppendFormat("GHI{0}{1}", 'J', 'k');

        // Display the number of characters in the StringBuilder and its string.
        Console.WriteLine("{0} chars: {1}", sb.Length, sb.ToString());

        // Insert a string at the beginning of the StringBuilder.
        sb.Insert(0, "Alphabet: ");

        // Replace all lowercase k's with uppercase K's.
        sb.Replace('k', 'K');

        // Display the number of characters in the StringBuilder and its string.
        Console.WriteLine("{0} chars: {1}", sb.Length, sb.ToString());
    }
}

// This code produces the following output.
//
// 11 chars: ABCDEFGHIJk
// 21 chars: Alphabet: ABCDEFGHIJK
10
BlackWasp

Je voudrais simplement dire que ce n'est pas nécessairement plus rapide, il aura certainement une meilleure empreinte mémoire. En effet, les chaînes sont immuables dans .NET et chaque fois que vous modifiez une chaîne, vous en créez une nouvelle.

3
smaclell

À propos d'une mémoire plus rapide/meilleure:

J'ai examiné ce problème avec Java, je suppose que .NET serait aussi intelligent à ce sujet.

L'implémentation de String est assez impressionnante.

L'objet String suit "longueur" et "partagé" (indépendamment de la longueur du tableau qui contient la chaîne)

Donc quelque chose comme

String a = "abc" + "def" + "ghi";

peut être implémenté (par le compilateur/runtime) comme:

 - Prolonge le tableau contenant "abc" de 6 espaces supplémentaires. 
 - Copie def à droite après abc 
 - copie ghi après def. 
 - donnez un pointeur sur la chaîne "abc" à un 
 - laissez la longueur de abc à 3, définissez la longueur de a à 9 
 - définissez le drapeau partagé dans les deux. .]

Étant donné que la plupart des chaînes sont de courte durée, cela donne du code TRÈS efficace dans de nombreux cas. Le cas où ce n'est absolument PAS efficace est lorsque vous ajoutez à une chaîne dans une boucle, ou lorsque votre code est comme ceci:

a = "abc";
a = a + "def";
a += "ghi";

Dans ce cas, il vaut mieux utiliser une construction StringBuilder.

Mon point est que vous devez être prudent chaque fois que vous optimisez, sauf si vous êtes ABSOLUMENT sûr de savoir ce que vous faites, ET vous êtes absolument sûr que c'est nécessaire, ET vous testez pour vous assurer que le code optimisé fait passer un cas d'utilisation, codez-le simplement de la manière la plus lisible possible et n'essayez pas de dépasser le compilateur.

J'ai perdu 3 jours à jouer avec les chaînes, à mettre en cache/réutiliser les générateurs de chaînes et à tester la vitesse avant de regarder le code source des chaînes et de comprendre que le compilateur le faisait déjà mieux que je ne le pouvais pour mon cas d'utilisation. Ensuite, j'ai dû expliquer comment je ne savais PAS VRAIMENT ce que je faisais, je pensais seulement que je le savais ...

2
Bill K

Il n'est pas plus rapide de concaténer - Comme l'a souligné smaclell, le problème est la chaîne immuable forçant une allocation supplémentaire et une recopie des données existantes.

"a" + "b" + "c" n'est pas plus rapide à faire avec le générateur de chaîne, mais les concatitions répétées avec une chaîne intermédiaire deviennent de plus en plus rapides à mesure que le # de concat est plus grand comme:

x = "a"; x + = "b"; x + = "c"; ...

1
Tony Lee