Combien d’objects Ssortingng seront créés lors de l’utilisation d’un signe plus?

Combien d’objects Ssortingng seront créés lors de l’utilisation d’un signe plus dans le code ci-dessous?

Ssortingng result = "1" + "2" + "3" + "4"; 

Si c’était comme ci-dessous, j’aurais dit trois objects Ssortingng: “1”, “2”, “12”.

 Ssortingng result = "1" + "2"; 

Je sais également que les objects Ssortingng sont mis en cache dans le pool / tableau de stagiaires de la chaîne pour améliorer les performances, mais ce n’est pas la question.

Étonnamment, cela dépend.

Si vous faites cela dans une méthode:

 void Foo() { Ssortingng one = "1"; Ssortingng two = "2"; Ssortingng result = one + two + "34"; Console.Out.WriteLine(result); } 

alors le compilateur semble émettre le code en utilisant Ssortingng.Concat comme @Joachim a répondu (+1 à lui btw).

Si vous les définissez comme des constantes , par exemple:

 const Ssortingng one = "1"; const Ssortingng two = "2"; const Ssortingng result = one + two + "34"; 

ou comme littéraux , comme dans la question initiale:

 Ssortingng result = "1" + "2" + "3" + "4"; 

alors le compilateur optimisera ces signes + . C’est équivalent à:

 const Ssortingng result = "1234"; 

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:

 const Ssortingng one = "1"; const Ssortingng two = "1"; const Ssortingng result = one + two + "34"; public static void main(ssortingng[] args) { Console.Out.WriteLine(result); } 

Ne génère qu’une seule chaîne: le result constant (égal à “1234”). one et two n’apparaissent pas dans l’IL résultant.

N’oubliez pas qu’il peut y avoir d’autres optimisations à l’exécution. Je ne fais que passer 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 internée est la valeur constante résultante dans l’IL, et non le littéral. Cela signifie que vous pourriez obtenir encore moins d’objects de chaîne que prévu, car plusieurs constantes ou littéraux définis de manière identique seront en réalité le même object! Ceci est illustré par ce qui suit:

 public class Program { private const Ssortingng one = "1"; private const Ssortingng two = "2"; private const Ssortingng RESULT = one + two + "34"; static Ssortingng MakeIt() { return "1" + "2" + "3" + "4"; } static void Main(ssortingng[] args) { ssortingng result = "1" + "2" + "34"; // Prints "True" Console.Out.WriteLine(Object.ReferenceEquals(result, MakeIt())); // Prints "True" also Console.Out.WriteLine(Object.ReferenceEquals(result, RESULT)); Console.ReadKey(); } } 

Dans le cas où les chaînes sont concaténées dans une boucle (ou dynamicment), vous obtenez 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 résultant en une nouvelle instance de Ssortingng:

 public class Program { static void Main(ssortingng[] args) { ssortingng result = ""; for (int i = 0; i < 10; i++) result += "a"; Console.ReadKey(); } } 

Mais (de manière surprenante), le compilateur combine plusieurs concaténations consécutives en une seule concaténation multi-chaînes. Par exemple, ce programme ne produit que 12 instances de chaîne! C'est parce que " Même si vous utilisez plusieurs opérateurs + dans une seule déclaration, le contenu de la chaîne est copié une seule fois. "

 public class Program { static void Main(ssortingng[] args) { ssortingng result = ""; for (int i = 0; i < 10; i++) result += "a" + result; Console.ReadKey(); } } 

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, j’appendais simplement deux points intéressants supplémentaires.

La première est que l’optimiseur de concaténation ignore essentiellement les parenthèses et l’associativité à gauche lorsque cela est possible en toute sécurité. Supposons que vous avez une méthode M () qui retourne une chaîne. Si tu le dis:

 ssortingng s = M() + "A" + "B"; 

alors le compilateur estime que l’opérateur d’addition est laissé associatif et que, par conséquent, il est identique à:

 ssortingng s = ((M() + "A") + "B"); 

Mais ça:

 ssortingng s = "C" + "D" + M(); 

est le même que

 ssortingng s = (("C" + "D") + M()); 

c’est donc la concaténation de la chaîne constante "CD" avec M() .

En fait, l’optimiseur de concaténation réalise que la concaténation de chaîne est associative et génère Ssortingng.Concat(M(), "AB") pour le premier exemple, même si cela viole l’associativité à gauche.

Vous pouvez même le faire:

 ssortingng s = (M() + "E") + ("F" + M())); 

et nous allons toujours générer Ssortingng.Concat(M(), "EF", M()) .

Le deuxième point intéressant est que les chaînes vides et nulles sont optimisées. Donc, si vous faites ceci:

 ssortingng s = (M() + "") + (null + M()); 

vous aurez Ssortingng.Concat(M(), M())

Une question intéressante est alors posée: qu’en est-il de cela?

 ssortingng s = M() + null; 

Nous ne pouvons pas optimiser cela jusqu’à

 ssortingng s = M(); 

car M() pourrait renvoyer null, mais Ssortingng.Concat(M(), null) renverrait une chaîne vide si M() renvoie null. Donc, ce que nous faisons est plutôt réduire

 ssortingng s = M() + null; 

à

 ssortingng s = M() ?? ""; 

Démontrant ainsi que la concaténation de chaînes n’a pas besoin d’appeler réellement Ssortingng.Concat .

Pour plus de lecture à ce sujet, voir

Pourquoi Ssortingng.Concat n’est-il pas optimisé pour SsortingngBuilder.Append?

J’ai trouvé la réponse sur MSDN. Un.

Comment: concaténer plusieurs chaînes (Guide de programmation C #)

La concaténation est le processus d’ajout d’une chaîne à la fin d’une autre chaîne. Lorsque vous concaténez des littéraux de chaîne ou des constantes de chaîne à l’aide de l’opérateur +, le compilateur crée une chaîne unique. Aucune concaténation à l’exécution n’a lieu. Cependant, les variables de chaîne ne peuvent être concaténées qu’au moment de l’exécution. Dans ce cas, vous devez comprendre les implications de performance des différentes approches.

Juste un. Le compilateur C # va plier les constantes de chaîne et par conséquent, il comstack essentiellement jusqu’à

 Ssortingng result = "1234"; 

Je doute que cela soit exigé par une norme ou une spécification. Une version peut probablement faire quelque chose de différent.

Un, car ils sont statiques, le compilateur sera capable de l’optimiser à une seule chaîne au moment de la compilation.

S’ils avaient été dynamics, ils auraient été optimisés pour un seul appel à Ssortingng.Concat (chaîne, chaîne, chaîne, chaîne) .