¿Cuántos objetos String se crearán cuando se use un signo más en el siguiente código?
String result = "1" + "2" + "3" + "4";
Si fuera como se muestra a continuación, habría dicho tres objetos String: "1", "2", "12".
String result = "1" + "2";
También sé que los objetos String se almacenan en caché en String Intern Pool / Table para mejorar el rendimiento, pero esa no es la cuestión.
Respuestas:
Sorprendentemente, depende.
Si haces esto en un método:
entonces el compilador parece emitir el código usando
String.Concat
como respondió @Joachim (+1 a él por cierto).Si los define como constantes , por ejemplo:
o como literales , como en la pregunta original:
entonces el compilador optimizará esos
+
signos. Es equivalente a:Además, el compilador eliminará expresiones constantes extrañas y solo las emitirá si se usan o se exponen. Por ejemplo, este programa:
Solo genera una cadena, la constante
result
(igual a "1234").one
ytwo
no aparecen en el IL resultante.Tenga en cuenta que puede haber más optimizaciones en tiempo de ejecución. Solo me guío por lo que IL se produce.
Finalmente, en lo que respecta al internado, se internan constantes y literales, pero el valor que se interpone es el valor constante resultante en el IL, no el literal. Esto significa que puede obtener incluso menos objetos de cadena de los que espera, ya que múltiples constantes o literales idénticamente definidos serán en realidad el mismo objeto. Esto se ilustra con lo siguiente:
En el caso de que las cadenas se concatenan en un bucle (o de otro modo de forma dinámica), se termina con una cadena adicional por concatenación. Por ejemplo, lo siguiente crea 12 instancias de cadena: 2 constantes + 10 iteraciones, cada una de las cuales da como resultado una nueva instancia de cadena:
Pero (también sorprendentemente), el compilador combina múltiples concatenaciones consecutivas en una sola concatenación de múltiples cadenas. Por ejemplo, este programa también solo produce 12 instancias de cadena. Esto se debe a que " Incluso si utiliza varios operadores + en una declaración, el contenido de la cadena se copia solo una vez " .
fuente
string s = ""; for (int i = 0; i < n; i++) s += "a";
La respuesta de Chris Shain es muy buena. Como persona que escribió el optimizador de concatenación de cadenas, solo agregaría dos puntos interesantes adicionales.
La primera es que el optimizador de concatenación esencialmente ignora tanto el paréntesis como la asociatividad izquierda cuando puede hacerlo de forma segura. Suponga que tiene un método M () que devuelve una cadena. Si usted dice:
entonces el compilador razona que el operador de suma es asociativo izquierdo, y por lo tanto esto es lo mismo que:
Pero esto:
es lo mismo que
de modo que esa es la concatenación de la cadena constante
"CD"
conM()
.De hecho, el optimizador de concatenación se da cuenta de que la concatenación de cadenas es asociativa y genera
String.Concat(M(), "AB")
para el primer ejemplo, aunque eso viola la asociatividad izquierda.Incluso puedes hacer esto:
y todavía generaremos
String.Concat(M(), "EF", M())
.El segundo punto interesante es que las cadenas nulas y vacías se optimizan. Entonces, si haces esto:
obtendrás
String.Concat(M(), M())
Entonces surge una pregunta interesante: ¿qué pasa con esto?
No podemos optimizar eso hasta
porque
M()
podría devolver nulo, peroString.Concat(M(), null)
devolvería una cadena vacía siM()
devuelve nulo. Entonces, lo que hacemos es reducira
De este modo, se demuestra que la concatenación de cadenas no necesita llamar
String.Concat
en absoluto.Para obtener más información sobre este tema, consulte
¿Por qué String.Concat no está optimizado para StringBuilder.Append?
fuente
("C" + "D") + M())
generaString.Concat("CD", M())
, noString.Concat(M(), "AB")
. Y más abajo,(M() + "E") + (null + M())
debe generarString.Concat(M(), "E", M())
, noString.Concat(M(), M())
.Encontré la respuesta en MSDN. Uno.
Cómo: Concatenar varias cadenas (Guía de programación de C #)
fuente
Solo uno. El compilador de C # plegará las constantes de cadena y, por lo tanto, esencialmente compila hasta
fuente
Dudo que esto sea obligatorio por cualquier estándar o especificación. Es probable que una versión pueda hacer algo diferente a otra.
fuente
Uno, dado que son estáticos, el compilador podrá optimizarlo a una sola cadena en tiempo de compilación.
Si hubieran sido dinámicos, se habrían optimizado para una sola llamada a String.Concat (cadena, cadena, cadena, cadena) .
fuente