2009-12-29 28 views
5

Entonces ... Tengo este escenario en el que tengo un bucle Foreach que recorre una Lista de casillas de verificación para verificar cuáles están seleccionadas. Para cada casilla de verificación seleccionada, tengo que hacer una concatenación de cadenas bastante larga, que implica 30 cadenas diferentes de una longitud promedio de 20 caracteres, y luego enviarla como una solicitud HTTP. 2 de las cadenas dependen del índice/valor de la casilla de verificación seleccionada.Concatenación de cadenas Vs Generador de cadenas Agregar

La longitud de la Lista de casillas de verificación también varía según los datos del usuario. Yo diría que la duración promedio de la Lista sería de 20, pero puede llegar a 50-60. Entonces, el peor de los escenarios sería realizar la concatenación de cadenas enteras 60 o más veces.

Por ahora lo hago con una simple concatenación de cadenas mediante el operador '+', pero me pregunto si sería más rápido hacerlo con Stringbuilder. Por supuesto, eso significa que tendré que crear un objeto Stringbuilder dentro del bucle, o crearlo antes del bucle y llamar a Stringbuilder. Eliminar al final después de enviar la solicitud HTTP.

Agradezco cualquier información que cualquiera pueda compartir sobre este tema.

EDITAR
Gracias por todo el todo el mundo, por lo que las respuestas de lo que he reunido, la mejor manera de que me vaya a hacer esto sería algo así como:

+0

Me disculpo, parece que no entiendo Stringbuilder lo suficiente. Entonces, ¿llamar a Stringbuilder.ToString() borra el Stringbuilder? – Kronon

+0

No. Establecer la propiedad Longitud a cero lo borra. –

+0

someStringBuilder.length = 0; –

Respuesta

14

Use StringBuilder. Para eso es para eso.

Las cadenas son inmutables. La concatenación de cadenas crea una nueva cadena, que necesitan más memoria, y en general se considera lento:

string a = "John" + " " + "Saunders"; 

Esto crea una cadena "John", a continuación, crea otra cadena "John Saunders", y finalmente, asigna esa "a" . El "Juan" queda para la recolección de basura.

string a = "John"; 
a += " "; 
a += "Saunders"; 

Esto es casi lo mismo, como "John" se sustituye por una nueva cadena "John", que se sustituye por una nueva cadena "John Saunders". Los originales quedan como basura.

Por otro lado, StringBuilder está diseñado para ser añadido, eliminado, etc.


Ejemplo:

StringBuilder sb = new StringBuilder(); 
for (int i=0; i<n; i++) 
{ 
    sb.Length = 0; 
    sb.Append(field1[i]); 
    sb.Append(field2[i]); 
    ... 
    sb.Append(field30[i]); 
    // Do something with sb.ToString(); 
} 
+0

por alguna razón, me ha gustado esta respuesta. –

+0

Me disculpo si mi pregunta parecía frívola, pero me preguntaba si la creación de un nuevo objeto Stringbuilder en cada ciclo llevaría a una sobrecarga innecesaria. – Kronon

+0

¿Por qué querrías crear uno nuevo? –

2

En general lo haría recomendamos usar un StringBuilder.

¿Has probado esto y verificado el rendimiento? ¿El rendimiento es un problema frente a cuánto tiempo le llevará reescribir el código?

+0

Ya terminé este proyecto, así que ahora solo estoy buscando varias formas de optimizar mi código para un mejor rendimiento. – Kronon

5

Este tema ha sido analizado a la muerte durante los años. El resultado final es que si está haciendo un número pequeño y conocido de concatenaciones, use '+', de lo contrario use stringbuilder. Por lo que has dicho, concatenar con '+' debería ser más rápido. Hay un montón de sitios (dar o recibir) analizando esto: google it.

Para el tamaño de la cadena que está hablando, es insignificante de todos modos.

EDITAR: en segundo lugar, SB es probablemente más rápido. Pero como dije, ¿a quién le importa?

+2

No estoy de acuerdo. Si está haciendo 30 operaciones "+", está asignando y descartando muchas cadenas, sin agregarlas a ninguna de ellas. –

+0

ingresó mientras editaba :) Creo que SB podría SOLO ser más rápido, pero recuerde que todo ese 'descarte' de cadenas lo maneja el GC, que hace un trabajo bastante eficiente y no es realmente manejado por la ruta de ejecución actual. –

+0

sigue siendo un trabajo GC innecesario que podría evitarse fácilmente ... no es como si estuviéramos hablando de 2 o 3 cuerdas ... –

2

Si está haciendo esta pregunta, es probable que deba usar StringBuilder por muchas razones, pero proporcionaré dos.

  1. Cuando se utiliza la concatenación de cadenas se tiene que asignar un nuevo buffer y copiar los datos y en la otra cadena en la nueva variable de cadena. Entonces vas a incurrir en muchas asignaciones repetidas. Que al final termina fragmentando la memoria, agotando el espacio de pila y haciendo más trabajo para el recolector de basura. StringBuilder, por otro lado, asigna previamente un búfer y, a medida que agrega cadenas, no necesita seguir reasignando (suponiendo que el búfer inicial sea lo suficientemente grande). Lo que aumenta el rendimiento y es mucho menos exigente en la memoria.

  2. Como desarrolladores, debemos tratar de anticipar el crecimiento futuro. Digamos que su lista crece sustancialmente con el tiempo y de repente comienza a funcionar lentamente. Si puede evitar esto con poco esfuerzo ahora, ¿por qué no lo haría?

6

Sé que esto ha sido contestada, pero quería señalar que en realidad creo que el enfoque de "ciegamente aceptado como un evangelio" de utilizar siempre StringBuilder es a veces mal, y este es uno de los casos.

Para los antecedentes, véase esta entrada de blog: http://geekswithblogs.net/johnsperfblog/archive/2005/05/27/40777.aspx

El corto de él es, en este caso particular, como se describe, se verá mejor rendimiento al evitar StringBuilder y haciendo uso del operador + de esta manera:

foreach (CheckBox item in FriendCheckboxList) 
{ 
    if (item.Checked) 
    { 
     string request = string1 + 
      string2 + 
      string3 + 
      . 
      . 
      . 
      stringLast; 
     SendRequest(request); 
    } 
} 

La razón es que el compilador de C# (a partir de .NET 1.1), convertirá esa instrucción en una única llamada IL a String.Concat pasando una matriz de cadenas como argumento. La entrada del blog hace un excelente trabajo al describir los detalles de implementación de String.Concat, pero basta con decir que es extremadamente eficiente para este caso.

+0

gracias por mencionar esto. Mucha gente asume que están guardando llamadas de GC cuando pueden no estarlo. Si está relacionado con el rendimiento y podría ser realmente importante, ¡mídelo! Hay muy pocas reglas de "usar siempre X" que sean correctas. –

+1

Cuando hay un número fijo de cadenas para concatenar, string.Concat es mucho mejor. Todo lo que necesita hacer es agregar el total de las longitudes de cadena, asignar memoria, copiar cada cadena, y listo. Si luego espera hacer más procesamiento, StringBuilder es probablemente mejor. – Todd