c# - how - stringbuilder net
Cómo usar StringBuilder sabiamente (3)
La modificación de estructuras immutable como string
s se debe hacer copiando la estructura y, por lo tanto, consumiendo más memoria y ralentizando el tiempo de ejecución de la aplicación (aumentando también el tiempo de GC
, etc.).
StringBuilder
viene a resolver este problema usando el mismo objeto mutable para manipulaciones.
Sin embargo:
al concatenar una string
en tiempo de compilación de la siguiente manera:
string myString = "123";
myString += "234";
myString += "345";
en realidad se compilará a algo así:
string myString = string.Concat("123", "234", "345");
esta función es más rápida que trabajar con StringBuilder
porque se conoce el número de string
entran en la función.
por lo tanto, para string
concatenaciones de string
conocidas en tiempo de compilación, debería preferir string.Concat()
.
en cuanto a la cantidad desconocida de string
como en el siguiente caso:
string myString = "123";
if (Console.ReadLine() == "a")
{
myString += "234";
}
myString += "345";
Ahora el compilador no puede usar la función string.Concat()
, sin embargo, StringBuilder
parece ser más eficiente en tiempo y consumo de memoria solo cuando la concatenación se hace con 6-7 o más strings
.
Uso de mala práctica:
StringBuilder myString = new StringBuilder("123");
myString.Append("234");
myString.Append("345");
Uso adecuado de la práctica (tenga en cuenta que if
se usa):
StringBuilder myString = new StringBuilder("123");
if (Console.ReadLine() == "a")
{
myString.Append("234");
}
myString.Append("345");
Uso de mejores prácticas (tenga en cuenta que while
loop se usa):
StringBuilder myString = new StringBuilder("123");
while (Console.ReadLine() == "a")
{
myString.Append("234"); //Average loop times 4~ or more
}
myString.Append("345");
Estoy un poco confundido sobre el uso de la clase StringBuilder
, primero:
Una operación de concatenación de objeto de
string
siempre crea un nuevo objeto a partir de lastring
existente y los datos nuevos. Un objetoStringBuilder
mantiene un búfer para acomodar la concatenación de datos nuevos. Se añaden nuevos datos al final del búfer si hay espacio disponible; de lo contrario, se asigna un nuevo búfer más grande, los datos del búfer original se copian en el nuevo búfer, y luego se añaden los nuevos datos al nuevo búfer.
Pero, ¿de qué sirve crear una instancia de StringBuilder
para evitar crear una nueva de String
? Suena como intercambiar "uno por uno".
static void Main(string[] args)
{
String foo = "123";
using (StringBuilder sb = new StringBuilder(foo)) // also sb isn''t disposable, so there will be error
{
sb.Append("456");
foo = sb.ToString();
}
Console.WriteLine(foo);
Console.ReadKey();
}
Por qué no debería simplemente usar
+=
Editar: Ok, ahora sé cómo volver a utilizar una instancia de StringBuilder
(todavía no sé si esto es correcto con los estándares de código), pero no vale la pena usarlo con una sola string
, ¿no es así?
La razón es porque las strings
son inmutables. Cuando concatena una string
, crea una nueva string
. Entonces, cuando necesitas concatenar muchas strings
, creas muchos objects
. Esto no cuesta mucho en términos de memoria, ya que cada string
se usa una vez. Pero da trabajo extra para el GC
.
Sin embargo, StringBuilder
utiliza el mismo object
cada vez, pero lo hace a expensas de la facilidad de uso.
Una string
es una clase inmutable . No puedes modificarlo, solo crear nuevas strings
.
Entonces cuando escribes result += a;
tiene tres strings
separadas en la memoria en ese punto: a
, el valor anterior del result
y el nuevo valor. Por supuesto, esto está absolutamente bien si solo concatena un número limitado de strings
. Si haces eso en un bucle for
iterando sobre una colección grande, puede convertirse en un problema.
La clase StringBuilder
ofrece un mejor rendimiento en estos casos. En lugar de crear nuevas strings
para almacenar el resultado de la concatenación, utiliza el mismo objeto. Entonces, si usas stringBuilder.Append(a);
nunca tiene el equivalente del "valor anterior de result
".
Esta eficiencia de memoria viene con un precio, por supuesto. Cuando solo concatena una pequeña cantidad de strings
un StringBuilder
suele ser menos eficiente en cuanto a la velocidad, ya que tenía más sobrecarga en comparación con la clase de string
inmutable.
Una cosa a tener en cuenta es que cuando necesita las cadenas intermedias, StringBuilder
puede volverse menos eficiente ya que al llamar a .ToString()
crea una nueva copia de la string
.