Cuándo usar StringBuilder?

Entiendo los beneficios de StringBuilder.

Pero si quiero concatenar 2 cadenas, entonces supongo que es mejor (más rápido) hacerlo sin StringBuilder. ¿Es esto correcto?

¿En qué punto (número de cadenas) se vuelve mejor usar StringBuilder?

Le sugiero encarecidamente que lea The Sad Tragedy of Micro-Optimization Theatre , de Jeff Atwood.

Trata la Concatenación simple vs. StringBuilder vs. otros métodos.

Ahora, si quieres ver algunos números y gráficos, sigue el enlace;)

Pero si quiero concatenación de 2 cadenas, supongo que es mejor (más rápido) hacerlo sin StringBuilder. ¿Es esto correcto?

Eso es cierto, puedes encontrar por qué exactamente se explica muy bien en:

http://www.yoda.arachsys.com/csharp/stringbuilder.html

En resumen: si puedes concatenar cadenas de una vez como

var result = a + " " + b + " " + c + .. 

es mejor sin stringbuilder porque solo se hace una copia (la longitud de la cadena resultante se calcula de antemano);

Para estructuradores como

 var result = a; result += " "; result += b; result += " "; result += c; .. 

nuevos objetos se crean cada vez, por lo que debe considerar StringBuilder.

Al final, el artículo resume estas reglas generales:

Reglas de juego

Entonces, ¿cuándo debería usar StringBuilder, y cuándo debería usar los operadores de concatenación de cadenas?

  • Definitivamente use StringBuilder cuando esté concatenándose en un bucle no trivial, especialmente si no sabe con certeza (en tiempo de comstackción) cuántas iteraciones realizará a través del bucle. Por ejemplo, leer un archivo de un personaje a la vez, construir una cadena sobre la marcha con el operador + = es potencialmente un suicidio de rendimiento.

  • Definitivamente use el operador de concatenación cuando pueda (legible) especificar todo lo que necesita concatenarse en una statement. (Si tiene una serie de elementos para concatenar, considere llamar a String.Concat explícitamente – o String.Join si necesita un delimitador).

  • No tenga miedo de dividir los literales en varios bits concatenados; el resultado será el mismo. Puede ayudar a la legibilidad dividiendo un literal largo en varias líneas, por ejemplo, sin dañar el rendimiento.

  • Si necesita los resultados intermedios de la concatenación para algo que no sea alimentar la próxima iteración de concatenación, StringBuilder no lo ayudará. Por ejemplo, si crea un nombre completo a partir de un nombre y un apellido, y luego agrega una tercera información (el alias, tal vez) hasta el final, solo se beneficiará de usar StringBuilder si no lo hace necesita la cadena (nombre + apellido) para otro fin (como lo hacemos en el ejemplo que crea un objeto Persona).

  • Si solo tiene algunas concatenaciones que hacer, y realmente desea hacerlas en declaraciones separadas, en realidad no importa qué camino tomar. El camino que sea más eficiente dependerá de la cantidad de concatenaciones, los tamaños de cadena implicados y el orden en que están concatenados. Si realmente crees que esa parte del código es un cuello de botella de rendimiento, perfila o compara ambos aspectos.

System.String es un objeto inmutable; significa que cada vez que modifique su contenido, asignará una nueva cadena y esto lleva tiempo (¿y memoria?). Usando StringBuilder puedes modificar el contenido real del objeto sin asignar uno nuevo.

Entonces usa StringBuilder cuando necesites hacer muchas modificaciones en la cadena.

En realidad, no … debería usar StringBuilder si concatena cadenas grandes o tiene muchas concatenaciones, como en un bucle.

Pero si quiero concatenación de 2 cadenas, supongo que es mejor (más rápido) hacerlo sin StringBuilder. ¿Es esto correcto?

Sí. Pero, lo que es más importante, es mucho más fácil usar strings vainilla en tales situaciones. Usarlo en un ciclo, por otro lado, tiene sentido y también puede ser tan legible como la concatenación.

Sería cauteloso con las reglas generales que citan números específicos de concatenación como un umbral. Usarlo en bucles (y bucles solamente) es probablemente igual de útil, más fácil de recordar y tiene más sentido.

No hay una respuesta definitiva, solo reglas generales. Mis propias reglas personales dicen algo como esto:

  • Si concatena en un bucle, siempre use un StringBuilder .
  • Si las cadenas son grandes, siempre use un StringBuilder .
  • Si el código de concatenación es ordenado y legible en la pantalla, entonces probablemente esté bien.
    Si no es así, use un StringBuilder .

Parafrasear

Entonces contarás hasta tres, ni más ni menos. Tres será el número que contarás, y el número del conteo será tres. Cuatro no contarás, ni contarás dos, excepto que luego pasarás a tres. Una vez que el número tres, siendo el tercer número, sea alcanzado, entonces suelta tu Mano Santa Granada de Antioquía

Generalmente utilizo el generador de cadenas para cualquier bloque de código que daría como resultado la concatenación de tres o más cadenas.

  • Si concatena cadenas en un bucle, debería considerar usar StringBuilder en lugar de String normal.
  • En caso de que se trate de una sola concatenación, es posible que no vea la diferencia en el tiempo de ejecución.

Aquí hay una aplicación de prueba simple para probar el punto:

 class Program { static void Main(string[] args) { const int testLength = 30000; var StartTime = DateTime.Now; //TEST 1 - String StartTime = DateTime.Now; String tString = "test string"; for (int i = 0; i < testLength; i++) { tString += i.ToString(); } Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString()); //result: 2000 ms //TEST 2 - StringBuilder StartTime = DateTime.Now; StringBuilder tSB = new StringBuilder("test string"); for (int i = 0; i < testLength; i++) { tSB.Append(i.ToString()); } Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString()); //result: 4 ms Console.ReadLine(); } } 

Resultados:

  • 30'000 iteraciones

    • Cadena - 2000 ms
    • StringBuilder - 4 ms
  • 1000 iteraciones

    • Cadena - 2 ms
    • StringBuilder - 1 ms
  • 500 iteraciones

    • Cadena - 0 ms
    • StringBuilder - 0 ms

Siempre que pueda escribir físicamente el número de concatenaciones (a + b + c …) no debería hacer una gran diferencia. N al cuadrado (en N = 10) es una ralentización de 100X, lo que no debería ser tan malo.

El gran problema es cuando concatena cientos de cadenas. En N = 100, obtienes una desaceleración de 10000X veces. Lo cual es bastante malo.

No creo que haya una línea fina entre cuándo usar o cuándo no. A menos, por supuesto, que alguien realice algunas pruebas exhaustivas para salir con las condiciones de oro.

Para mí, no usaré StringBuilder solo concatenar 2 cadenas enormes. Si hay un ciclo con un recuento indeterminado, es probable que lo haga, incluso si el ciclo fuera pequeño.

Una sola concatenación no vale la pena usar un generador de cuerdas. Normalmente he usado 5 concatenaciones como regla general.