La façon la plus efficace de concaténer des cordes?

Quelle est la façon la plus efficace de concaténer les cordes?

240
demandé sur Alex Angas 2008-08-22 00:27:15
la source

17 ответов

la méthode StringBuilder.Append() est bien meilleure que l'utilisation de l'opérateur+. Mais j'ai trouvé que, lors de l'exécution de 1000 concaténations ou moins, String.Join() est encore plus efficace que StringBuilder .

StringBuilder sb = new StringBuilder();
sb.Append(someString);

le seul problème avec String.Join est que vous devez concaténer les chaînes avec un délimiteur commun. (Edit:) comme @ryanversaw l'a fait remarquer, vous pouvez faire la chaîne de délimiteur.Vide.

string key = String.Join("_", new String[] 
{ "Customers_Contacts", customerID, database, SessionID });
131
répondu TheEmirOfGroofunkistan 2017-10-12 09:59:16
la source

Rico Mariani , le gourou de la Performance.net, avait un article sur ce même sujet. Ce n'est pas aussi simple qu'on pourrait le soupçonner. Le Conseil de base est le suivant:

si votre motif ressemble à:

x = f1(...) + f2(...) + f3(...) + f4(...)

c'est une concat et c'est zippy, StringBuilder n'aidera probablement pas.

Si votre motif ressemble:

if (...) x += f1(...)

if (...) x += f2(...)

if (...) x += f3(...)

if (...) x += f4(...)

alors vous voulez probablement StringBuilder.

encore un autre article à l'appui de cette allégation vient D'Eric Lippert où il décrit les optimisations effectuées sur une ligne + concaténations de manière détaillée.

243
répondu Lee 2016-08-26 07:37:11
la source

il y a 6 types de concaténations de chaîne:

  1. utilisant le symbole plus ( + ).
  2. par string.Concat() .
  3. par string.Join() .
  4. par string.Format() .
  5. par string.Append() .
  6. par StringBuilder .

Dans une expérience, il a été prouvé que string.Concat() est le meilleur moyen pour approcher si les mots sont moins de 1000 (approximativement) et si les mots sont plus de 1000 alors StringBuilder doit être utilisé.

pour plus d'informations, consultez ce site .

de la chaîne.Join() vs string.Concat ()

la corde.La méthode Concat ici est équivalente à la chaîne.Rejoignez l'appel de méthode avec un vide séparateur. En ajoutant une chaîne vide est rapide, mais ne pas le faire est encore plus rapide, donc la chaîne .La méthode Concat serait supérieure ici.

66
répondu Mr_Green 2017-01-26 15:51:12
la source

à Partir de Chinh Faire - StringBuilder n'est pas toujours plus rapide :

Règles d'or

  • lorsque vous concaténez trois valeurs de chaîne dynamique ou moins, utilisez la concaténation traditionnelle de chaîne.

  • lorsque vous concaténez plus de trois valeurs de chaîne dynamique, utilisez StringBuilder.

  • quand construire une grande chaîne à partir de plusieurs chaînes de caractères littérales, utilisez soit le @ string littéral ou l'opérateur inline+.

Plus de l'époque StringBuilder est votre meilleur pari, mais il y a des cas, comme indiqué dans ce post que vous devriez au moins penser à chaque situation.

51
répondu palehorse 2008-08-22 00:34:36
la source

si vous opérez en boucle, StringBuilder est probablement la solution; cela vous évite de créer régulièrement de nouvelles cordes. En code qui ne s'exécute qu'une fois, String.Concat est probablement très bien.

Cependant, Rico Mariani (.NET optimisation gourou) , constitué d'un questionnaire dans lequel il est dit à la fin que, dans la plupart des cas, il recommande à la Chaîne.Format.

11
répondu Adam V 2008-08-22 00:35:39
la source

de ce article MSDN :

Il ya certains frais généraux associés à création d'un objet StringBuilder, à la fois en temps et en mémoire. Sur une machine avec mémoire rapide, un StringBuilder devient ça en vaut la peine si vous en faites cinq. opérations. En règle générale, je disons 10 opérations de chaîne ou plus est une justification pour les frais généraux sur n'importe quelle machine, même plus lente.

Donc, si vous faites confiance à MSDN, allez avec StringBuilder si vous devez faire plus de 10 opérations/concaténations de chaînes - sinon simple chaîne concat avec '+' est très bien.

6
répondu JohnIdol 2015-07-22 11:51:12
la source

Voici la méthode la plus rapide que j'ai développée au cours d'une décennie pour mon application NLP à grande échelle. J'ai des variations pour IEnumerable<T> et d'autres types d'entrées, avec et sans séparateurs de différents types ( Char , String ), mais ici je montre le cas simple de concaténant toutes les chaînes dans un tableau dans une seule chaîne, sans séparateur. La dernière version ici est développé et testé à l'unité sur C# 7 et .NET 4.7 .

il y a deux clés pour des performances plus élevées; la première est de calculer à l'avance la taille totale exacte requise. Cette étape est triviale lorsque l'entrée est un tableau comme montré ici. Pour gérer IEnumerable<T> à la place, il est utile de rassembler les chaînes dans un tableau temporaire pour calculer ce total (le tableau est nécessaire pour éviter d'appeler ToString() plus d'une fois par élément car techniquement, compte tenu de la possibilité d'effets secondaires, faire ainsi pourrait changer la sémantique attendue d'une opération de 'jointure de chaîne').

ensuite, étant donné la taille totale de l'allocation de la chaîne finale, la plus grande augmentation de la performance est obtenue par la construction de la chaîne de résultat en place . Cela nécessite la technique (peut-être controversée) de suspendre temporairement l'immuabilité d'un nouveau String qui est initialement attribué plein de zéros. De telles controverses mises à part, cependant...

...notez qu'il s'agit de la seule solution de concaténation en vrac sur cette page qui évite totalement un round supplémentaire d'allocation et de copie par le String constructeur.

code complet:

/// <summary>
/// Concatenate the strings in 'rg', none of which may be null, into a single String.
/// </summary>
public static unsafe String StringJoin(this String[] rg)
{
    int i;
    if (rg == null || (i = rg.Length) == 0)
        return String.Empty;

    if (i == 1)
        return rg[0];

    String s, t;
    int cch = 0;
    do
        cch += rg[--i].Length;
    while (i > 0);
    if (cch == 0)
        return String.Empty;

    i = rg.Length;
    fixed (Char* _p = (s = new String(default(Char), cch)))
    {
        Char* pDst = _p + cch;
        do
            if ((t = rg[--i]).Length > 0)
                fixed (Char* pSrc = t)
                    memcpy(pDst -= t.Length, pSrc, (UIntPtr)(t.Length << 1));
        while (pDst > _p);
    }
    return s;
}

[DllImport("MSVCR120_CLR0400", CallingConvention = CallingConvention.Cdecl)]
static extern unsafe void* memcpy(void* dest, void* src, UIntPtr cb);

je dois mentionner que ce code a une légère modification de ce que je me sers moi-même. Dans l'original, I appelez le cpblk il instruction de c# pour faire la copie réelle. Pour la simplicité et la portabilité dans le code ici, je l'ai remplacé par P/invoquer memcpy à la place, comme vous pouvez le voir. Pour les performances les plus élevées sur x64 ( mais peut-être pas x86 ), vous pouvez utiliser la méthode cpblk à la place.

6
répondu Glenn Slayden 2017-11-11 01:06:05
la source

Ajouter aux autres réponses, s'il vous plaît garder à l'esprit que StringBuilder peut être dit une quantité initiale de mémoire pour allouer .

le paramètre capacity définit le nombre maximum de caractères pouvant être stockés dans la mémoire attribuée par l'instance courante. Sa valeur est attribuée à la propriété Capacity . Si le nombre de caractères à stocker dans le courant l'instance dépasse cette valeur capacity , L'objet StringBuilder alloue de la mémoire supplémentaire pour les stocker.

si capacité est zéro, la capacité par défaut spécifique à la mise en œuvre est utilisée.

ajouter à plusieurs reprises à un compilateur de cordes qui n'a pas été pré-alloué peut entraîner beaucoup d'allocations inutiles tout comme concaténer à plusieurs reprises des cordes régulières.

si vous savez combien de temps la chaîne finale sera, peut la calculer trivialement, ou peut faire une supposition instruite sur le cas commun (allouer trop n'est pas nécessairement une mauvaise chose), vous devriez fournir cette information au constructeur ou la propriété Capacity . en particulier lors de l'exécution de tests de performance pour comparer StringBuilder avec D'autres méthodes comme String.Concat, qui font la même chose en interne. Tous les tests que vous voyez en ligne ce qui n'inclut pas la pré-allocation de StringBuilder dans ses comparaisons est une erreur.

si vous ne pouvez pas deviner la taille, vous écrivez probablement une fonction utilitaire qui devrait avoir son propre argument optionnel pour contrôler la pré-allocation.

5
répondu DBN 2014-10-31 20:43:24
la source

il est également important de souligner que vous devez utiliser l'opérateur + si vous concaténez string literals .

lorsque vous concaténez des caractères littéraux ou des constantes de chaîne en utilisant l'opérateur+, le compilateur crée une chaîne unique. Aucune concaténation de durée d'exécution ne se produit.

Comment: Concaténer Plusieurs Chaînes de caractères (Guide de Programmation C#)

4
répondu talles 2013-10-14 21:15:53
la source

ci-dessous peut être une autre solution pour concaténer plusieurs chaînes.

String str1 = "sometext";
string str2 = "some other text";

string afterConcate = $"{str1}{str2}";

interpolation de chaîne

3
répondu RP Nainwal 2017-09-23 00:29:50
la source

le plus efficace est D'utiliser StringBuilder, comme ainsi:

StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();

@jonezy: String.Concat est très bien si vous avez quelques petites choses. Mais si vous concaténez des mégaoctets de données, votre programme sera probablement tank.

2
répondu TheSmurf 2008-08-22 00:28:13
la source

cela dépend vraiment de votre usage. Détaillée de référence entre la chaîne.Rejoindre, string Concat et de la corde.Le Format peut être trouvé ici: chaîne.Le Format n'est pas adapté à L'exploitation forestière Intensive

(c'est en fait la même réponse que j'ai donnée à cette" question 151920920") 151930920"

1
répondu Liran 2017-05-23 13:31:19
la source
Système

.La corde est immuable. Lorsque nous modifions la valeur d'une variable chaîne de caractères, alors une nouvelle mémoire est attribuée à la nouvelle valeur et l'ancienne attribution de mémoire est libérée. Système.StringBuilder a été conçu pour avoir le concept d'une chaîne mutable où une variété d'opérations peuvent être effectuées sans allocation d'emplacement mémoire séparé pour la chaîne modifiée.

1
répondu Dhibi_Mohanned 2014-04-24 14:27:10
la source

essayez ces 2 morceaux de code et vous trouverez la solution.

 static void Main(string[] args)
    {
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < 10000000; i++)
        {
            s.Append( i.ToString());
        }
        Console.Write("End");
        Console.Read();
    }

Vs

static void Main(string[] args)
    {
        string s = "";
        for (int i = 0; i < 10000000; i++)
        {
            s += i.ToString();
        }
        Console.Write("End");
        Console.Read();
    }

vous constaterez que le 1er code se terminera très rapidement et la mémoire sera en bonne quantité.

le second code peut-être que la mémoire sera ok, mais ça prendra plus de temps... beaucoup plus de temps. Donc si vous avez une application pour beaucoup d'utilisateurs et que vous avez besoin de vitesse, Utilisez la 1ère. Si vous avez une application à court terme une application utilisateur, peut-être que vous pouvez utiliser les deux ou le 2nd sera plus "naturel" pour les développeurs.

santé.

1
répondu Eduardo Mass 2016-01-01 20:25:37
la source

pour seulement deux cordes, vous ne voulez certainement pas utiliser StringBuilder. Il y a un certain seuil au-dessus duquel le StringBuilder overhead est inférieur au overhead de l'allocation de plusieurs chaînes.

donc, pour plus que 2-3 cordes, utilisez code de DannySmurf . Sinon, il suffit d'utiliser l'opérateur+.

0
répondu Nick 2017-05-23 13:31:19
la source

ça dépend du code. StringBuilder est généralement plus efficace, mais si vous concaténez seulement quelques chaînes et que vous faites tout en une seule ligne, les optimisations de code s'en chargeront probablement pour vous. Il est important de penser à l'apparence du code: pour les plus grands ensembles, StringBuilder le rendra plus facile à lire, pour les plus petits, StringBuilder ajoutera simplement un encombrement inutile.

0
répondu Jon Dewees 2008-08-22 00:34:49
la source

une autre solution:

dans la boucle, utilisez List au lieu de string.

List<string> lst= new List<string>();

for(int i=0; i<100000; i++){
    ...........
    lst.Add(...);
}
return String.Join("", lst.ToArray());;

c'est très rapide.

0
répondu asady 2018-01-19 15:19:52
la source

Autres questions sur c# string .net optimization