Combien d'objets String seront créés lors de l'utilisation d'un signe plus dans le code ci-dessous?
String result = "1" + "2" + "3" + "4";
Si c'était comme ci-dessous, j'aurais dit trois objets String: "1", "2", "12".
String result = "1" + "2";
Je sais également que les objets String sont mis en cache dans le pool / table String Intern pour améliorer les performances, mais ce n'est pas la question.
Réponses:
Étonnamment, cela dépend.
Si vous faites cela dans une méthode:
puis le compilateur semble émettre le code en utilisant
String.Concat
comme @Joachim a répondu (+1 pour lui btw).Si vous les définissez comme des constantes , par exemple:
ou comme littéraux , comme dans la question d'origine:
alors le compilateur optimisera ces
+
signes. C'est équivalent à:De plus, le compilateur supprimera les expressions constantes superflues et ne les émettra que si elles sont utilisées ou exposées. Par exemple, ce programme:
Ne génère qu'une seule chaîne - la constante
result
(égale à "1234").one
ettwo
n'apparaissent pas dans l'IL résultante.Gardez à l'esprit qu'il peut y avoir d'autres optimisations lors de l'exécution. Je vais juste par ce que IL est produit.
Enfin, en ce qui concerne l'internement, les constantes et les littéraux sont internés, mais la valeur qui est internée est la valeur constante résultante dans l'IL, pas le littéral. Cela signifie que vous pourriez obtenir encore moins d'objets chaîne que vous ne le pensez, car plusieurs constantes ou littéraux définis de manière identique seront en fait le même objet! Ceci est illustré par ce qui suit:
Dans le cas où les chaînes sont concaténées dans une boucle (ou autrement dynamiquement), vous vous retrouvez avec une chaîne supplémentaire par concaténation. Par exemple, ce qui suit crée 12 instances de chaîne: 2 constantes + 10 itérations, chacune aboutissant à une nouvelle instance de chaîne:
Mais (aussi étonnamment), plusieurs concaténations consécutives sont combinées par le compilateur en une seule concaténation multi-chaînes. Par exemple, ce programme ne produit également que 12 instances de chaîne! En effet, « même si vous utilisez plusieurs opérateurs + dans une instruction, le contenu de la chaîne n'est copié qu'une seule fois » .
la source
string s = ""; for (int i = 0; i < n; i++) s += "a";
La réponse de Chris Shain est très bonne. En tant que personne qui a écrit l'optimiseur de concaténation de chaînes, je voudrais simplement ajouter deux points intéressants supplémentaires.
Le premier est que l'optimiseur de concaténation ignore essentiellement les parenthèses et l'associativité gauche lorsqu'il peut le faire en toute sécurité. Supposons que vous ayez une méthode M () qui renvoie une chaîne. Si tu le dis:
alors le compilateur explique que l'opérateur d'addition reste associatif, et c'est donc la même chose que:
Mais ça:
est le même que
c'est donc la concaténation de la chaîne constante
"CD"
avecM()
.En fait, l'optimiseur de concaténation se rend compte que la concaténation de chaînes est associative et génère
String.Concat(M(), "AB")
pour le premier exemple, même si cela viole l'associativité gauche.Vous pouvez même faire ceci:
et nous allons toujours générer
String.Concat(M(), "EF", M())
.Le deuxième point intéressant est que les chaînes nulles et vides sont optimisées. Donc si vous faites ceci:
tu auras
String.Concat(M(), M())
Une question intéressante se pose alors: qu'en est-il de cela?
Nous ne pouvons pas optimiser cela jusqu'à
car
M()
pourrait renvoyer null, maisString.Concat(M(), null)
retournerait une chaîne vide siM()
renvoie null. Donc ce que nous faisons, c'est plutôt réduireà
Démontrant ainsi que la concaténation de chaînes n'a pas besoin d'appeler
String.Concat
du tout.Pour plus d'informations sur ce sujet, voir
Pourquoi String.Concat n'est-il pas optimisé pour StringBuilder.Append?
la source
("C" + "D") + M())
génèreString.Concat("CD", M())
, nonString.Concat(M(), "AB")
. Et plus bas,(M() + "E") + (null + M())
devrait générerString.Concat(M(), "E", M())
, nonString.Concat(M(), M())
.J'ai trouvé la réponse chez MSDN. Une.
Guide pratique pour concaténer plusieurs chaînes (Guide de programmation C #)
la source
Juste un. Le compilateur C # pliera les constantes de chaîne et par conséquent, il se compile essentiellement en
la source
Je doute que cela soit imposé par une norme ou une spécification. Une version peut probablement faire quelque chose de différent d'une autre.
la source
Premièrement, comme ils sont statiques, le compilateur pourra l'optimiser en une seule chaîne au moment de la compilation.
S'ils avaient été dynamiques, ils auraient été optimisés pour un seul appel à String.Concat (chaîne, chaîne, chaîne, chaîne) .
la source