IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

L'utilité de l'utilisation de la classe StringBuilder.


Sujet :

C#

  1. #1
    Membre éclairé
    Inscrit en
    Février 2006
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 373
    Par défaut L'utilité de l'utilisation de la classe StringBuilder.
    Bonjour,

    On sait que la classe StringBuilder est souvent utilsée à la place de la classe String lorsqu'on veut utiliser plusieurs manipulations des chaînes de caractères pour économiser les ressources. En effet, supposons qu'on veut avoir une grande chaîne de caractères par la concaténation de plusieurs sous-chaînes de caractères:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    string ch1="Bonjour, ";
    string ch2="comment ça va ?";
    ch1+=ch2;
    ...
    ch3="Tu as des questions à poser....";
    ch1+=ch3;
    .
    ..
    ...
    Sur la troisième ligne la référence ch1 pointe vers une nouvelle chaîne qui est "bonjour, comment ça va ?", et l'ancienne chaîne sera innaccessible, parce que String gére des chaînes de caractères immuables (non modifiables), et par la suite et à cause d'augmentation des chaînes innaccessibles on va consommer beaucoup des ressources. la solution c'est la StringBuilder qui gére les chaînes modifiables c-a-d on peut modifier la chaîne par concaténation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    StringBuilder sb = new StringBuilder(capacity, maxCapacity); 
     
    sb.Append(" Bonjour, "); 
     
    sb.Append("comment ca va ?");  
     
    sb.Append("Tu as des questions à poser....");  
    .
    ..
    ...
    Grâce à ça, on peut economiser les ressources.

    Mais, ma question c'est: En cas d'utilisation des chaînes de caractères de la classe String, est-ce que le Garbage Collector ne supprime pas automatiqiement les chaînes innaccessibles? si oui : donc on n'a pas besoin de StringBuilder.
    Merci d'avance de votre explication.

  2. #2
    Membre éprouvé
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Par défaut
    Il s'agit pas vraiment d'économiser de la place mais d'éviter de devoir entièrement réallouer un buffer en mémoire chaque fois qu'on fait une modification si petite soit-elle.

    Imagine que tu une chaine de 300'000 caractères en mémoire. et que tu dois modifier le dernier caractère... ou n'importe lequel c'est égal.
    Si tu as un String, le framework va réallouer un nouveau buffer de 600ko et y copier le résultat, tandis que si c'est un StringBuilder, il modifiera direct la chaine initiale.

    Pour ce qui est de la concaténation, le principe est le même, on modifie direct la chaine initiale jusqu'a ce qu'on excède la taille prévue (propriété Capacity). Si vous voulez être performant, donner toujours des tailles initiales larges si vous savez par avance de quoi vous avez besoin, même remarque pour les List<> et autres collections.

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Par défaut
    Salut,

    comme dit Skip, le probleme c'est pas tant la place en tant que tel, mais plutot qu'en te servant de string pour des concatenation dans une boucle, tu va tuer ton GC. La memoire, il la recuperera toujours, par contre le forcer avec ce genre de comportement, c'est vraiment un gouffre en terme de perf. Bref, quand tu penses string, += et boucle, c'est stringbuilder.

    Par contre pour revenir sur la concetanation, le fait de manipuler des chaines ne doit pas forcement induire l'utilisation d'un stringbuilder. Par exemple, dans le code que tu as donné, on peut tout à fait passer et avec des performances meilleures, par une simple concatenation de string :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    string ch1 = "Bonjour, ",  ch2 = "comment ça va ?", ch3="Tu as des questions à poser....";
    string result = ch1 + ch2 + ch3;
    En fait, tu peux faire ca jusqu'à 4 chaines (apres c'est un peu different) de maniere tout à fait efficiente. Ceci tient du fait que les 3 chaines sont connues et qu'on ne boucle nul part. A contrario, si on avait été obligé de concatener en plusieurs fois (result += ch1 .... result += ch2 .... [ad libitum]), alors la oui un stringbuilder aurait été interressant.

    Pour en revenir aux nombres de chaines, la classe string possede la methode static Concat avec de nombreuses surcharges, et particulierement Concat(string, string, [string], [string]). Ce sont ces dernieres qui sont appelés quand tu fais un + ou un += sur un string. Quand il y a plus de 4 chaines, il existe une autre surcharge (Concat(string[])) qui va concatener à partir d'un tableau de string (qui sera créé dans le code si tu additionnes plus de 4 strings). Le fonctionnement des Concat est de te retourner une chaine exactement à la bonne taille et ce, sans allocation temporaire (le fonctionnement sous-jacent est exactement le meme que celui d'un stringbuilder). Si par exemple, tu dois te retrouver à concatener un tableau de string, n'utilise pas un stringbuilder (comme beaucoup d'articles le proposent des qu'il s'agit de manipuler des strings) mais utilise plutot un Concat(string[]), le tableau etant deja existant tu n'auras aucun surcout d'instanciation de tableau, et quelque soit la taille du tableau, tu es garanti de n'avoir qu'une seule allocation, celle du resultat final.

    Bref, StringBuilder a une raison d'etre et dans beaucoup de manipulation de chaine, elle sera tout à fait adaptée, mais il ne faut pas forcement totalement exclure la possiblité de concatenation 'simple' par rapport aux autres, qui dans certains cas s'avere etre la meilleure solution, à savoir la concatenation de tableau, les manipulation impliquant peu de chaine avec la plupart des manipulation faisable en une seule fois et aussi ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
            void FormatVsConcat(string name)
            {
                Stopwatch sw = new Stopwatch();
     
                sw.Start();
                for (int i = 0; i < 1000000; i++)
                {
                    string s = string.Format("Salut {0}, ca va {0}", name);
                }
                sw.Stop();
                Trace.WriteLine(string.Format("Format : {0} ms", sw.ElapsedMilliseconds));
                sw.Reset();
     
                sw.Start();
                for (int i = 0; i < 1000000; i++)
                {
                    string s = "Salut " + name + ", ca va " + name;
                }
                sw.Stop();
                Trace.WriteLine(string.Format("Concat : {0} ms", sw.ElapsedMilliseconds));
            }
    la concatenation est, ici, la meilleure solution puisqu'en release, on (enfin je) obtient un facteur de 1 pour 5.

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 193
    Par défaut
    (lu en diagonale)

    le stringbuilder est en général utilisé non pas pour économiser de la mémoire, mais pour ses performances

    le meme traitement avec un stringbuilder est beaucoup plus rapide qu'avec un string (réellement significatif sur certains traitements)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre éclairé
    Inscrit en
    Février 2006
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 373
    Par défaut
    Merci beaucoup !

  6. #6
    Membre éprouvé
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Par défaut
    string s = "Salut " + name + ", ca va " + name;

    avec ce genre de traitement, le framework va automatiquement utliser un StringBuilder derrière de façon transparente.

  7. #7
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 193
    Par défaut
    le stringbuilder est utile dans des boucles
    le reste du temps surtout si on est pas maniaque on peut s'en passer
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Par défaut
    Citation Envoyé par _skip Voir le message
    string s = "Salut " + name + ", ca va " + name;

    avec ce genre de traitement, le framework va automatiquement utliser un StringBuilder derrière de façon transparente.
    Non, non, justement. Le seul stringbuilder "masqué" par le framework est celui des string.Format(). En additionnant, des strings, il appelera juste la surcharge de Concat specifique (2, 3, 4 arguments ou encore un tableau d'objet ou de string). Et c'est la l'avantage (minime certes), Concat ne créé pas de buffer comme un stringbuilder, mais directement un string de la bonne taille, et y copie dedans les arguments que tu as passé (par boucle sur les chars pour bypasser le comportement habituel d'un string).

    Bon bien sur, on pinaille ce sont des optimisations extremement minimes, hein =)

  9. #9
    Membre éprouvé
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Par défaut
    Alors... c'est java qui fait ça
    Petit brassage emmelement de pinceaux bref.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Servlet] Utilisation de plusieurs classes
    Par hedgehog dans le forum Servlets/JSP
    Réponses: 4
    Dernier message: 04/05/2005, 09h43
  2. Utilisation de la classe List de STL avec wxWidgets
    Par aoyou dans le forum wxWidgets
    Réponses: 7
    Dernier message: 10/03/2005, 17h41
  3. Réponses: 8
    Dernier message: 22/12/2004, 22h57
  4. [SWT] Utilisation de la classe Tracker
    Par arN34 dans le forum SWT/JFace
    Réponses: 2
    Dernier message: 24/11/2004, 10h28
  5. Réponses: 2
    Dernier message: 18/05/2004, 14h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo