Pregunta

Digamos que usted desea de salida o de concatenación de cadenas de caracteres.Cuál de los siguientes estilos te gusta más?

  • var p = new { FirstName = "Bill", LastName = "Gates" };

  • Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

  • Console.WriteLine(p.FirstName + " " + p.LastName);

¿En lugar de utilizar el formato o simplemente de concatenación de cadenas?¿Cuál es tu favorito?Es uno de estos lastimar tus ojos?

¿Tienes ningún argumento racional para el uso de uno y no el otro?

Yo iría a por el segundo.

¿Fue útil?

Solución

Prueba este código.

Es una versión ligeramente modificada de su código.
1.He quitado de la Consola.WriteLine como probablemente algunos órdenes de magnitud más lento que lo que estoy tratando de medir.
2.Estoy empezando el Cronómetro antes de que el bucle y de parar a la derecha después de que, de esta manera no estoy perdiendo precisión si la función toma por ejemplo 26.4 de las garrapatas a ejecutar.
3.La forma en que se divide el resultado por algunas iteraciones estaba equivocado.A ver qué pasa si usted tiene 1000 milisegundos y 100 milisegundos.En ambas situaciones, obtendrá 0 ms después de dividir por 1000000.

Stopwatch s = new Stopwatch();

var p = new { FirstName = "Bill", LastName = "Gates" };

int n = 1000000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;

string result;
s.Start();
for (var i = 0; i < n; i++)
    result = (p.FirstName + " " + p.LastName);
s.Stop();
cElapsedMilliseconds = s.ElapsedMilliseconds;
cElapsedTicks = s.ElapsedTicks;
s.Reset();
s.Start();
for (var i = 0; i < n; i++)
    result = string.Format("{0} {1}", p.FirstName, p.LastName);
s.Stop();
fElapsedMilliseconds = s.ElapsedMilliseconds;
fElapsedTicks = s.ElapsedTicks;
s.Reset();


Console.Clear();
Console.WriteLine(n.ToString()+" x result = string.Format(\"{0} {1}\", p.FirstName, p.LastName); took: " + (fElapsedMilliseconds) + "ms - " + (fElapsedTicks) + " ticks");
Console.WriteLine(n.ToString() + " x result = (p.FirstName + \" \" + p.LastName); took: " + (cElapsedMilliseconds) + "ms - " + (cElapsedTicks) + " ticks");
Thread.Sleep(4000);

Esos son mis resultados:

1000000 x resultado = cadena.Formato("{0} {1}", p.FirstName, p.LastName);tomó:618ms - 2213706 las garrapatas
1000000 x resultado = (p.Nombre + "" + p.LastName);tomó:166ms - 595610 las garrapatas

Otros consejos

Estoy sorprendido de que tantas personas de inmediato quiere encontrar el código que se ejecuta más rápido. Si UN MILLÓN de iteraciones que AÚN tardaría menos de un segundo proceso, va a ser esta, en CUALQUIER FORMA perceptible para el usuario final?No es muy probable.

Prematuro de optimización = FAIL.

Me gustaría ir con el String.Format opción, sólo porque tiene más sentido desde un punto de vista arquitectónico.No me importa el rendimiento hasta que se convierte en un problema (y si lo hizo, yo le pregunto:Necesito concatenar un millón de nombres a la vez?Seguramente no caben todos en la pantalla...)

Considere si su cliente más tarde quiere cambiar para que se pueden configurar si se mostrará "Firstname Lastname" o "Lastname, Firstname." Con la opción de Formato, esto es fácil - simplemente cambie la cadena de formato.Con la concat, usted necesita código extra.Seguro que no suena como un gran problema en este ejemplo en particular, pero extrapolar.

Oh, querido - después de la lectura de una de las otras respuestas que he intentado invertir el orden de las operaciones para la realización de la concatenación en primer lugar, a continuación, la Cadena.Formato de...

Bill Gates
Console.WriteLine(p.FirstName + " " + p.LastName); took: 8ms - 30488 ticks
Bill Gates
Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took: 0ms - 182 ticks

De modo que el orden de las operaciones que hace una GRAN diferencia, o más bien la primera operación es SIEMPRE mucho más lento.

Aquí es el resultado de una carrera en la que las operaciones son realizadas más de una vez.He intentado cambiar las órdenes, pero las cosas en general, siguen las mismas reglas, una vez que el primer resultado es ignorado:

Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 5ms - 20335 ticks
Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 0ms - 156 ticks
Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 0ms - 122 ticks
Bill Gates
Console.WriteLine("{0} {1}", FirstName, LastName); took: 0ms - 181 ticks
Bill Gates
Console.WriteLine("{0} {1}", FirstName, LastName); took: 0ms - 122 ticks
Bill Gates
String.Concat(FirstName, " ", LastName); took: 0ms - 142 ticks
Bill Gates
String.Concat(FirstName, " ", LastName); took: 0ms - 117 ticks

Como se puede ver las siguientes ejecuciones del mismo método (I refactorizado el código en 3 métodos) son incrementalmente más rápido.La forma más rápida parece ser la Consola.WriteLine(Cadena.Concat (...) método, seguido por normal concatenación y, a continuación, el formato de las operaciones.

El retraso inicial en la puesta en marcha es probable que la inicialización de la Consola de Flujo, como la colocación de una Consola.Writeline("Start!") antes de la primera operación trae todos los tiempos de vuelta en línea.

Las cadenas son inmutables, esto significa que el mismo pedazo pequeño de memoria se utiliza más y más en su código.La adición de la misma dos cadenas juntas y la creación de la misma cadena una y otra vez no afecta a la memoria..Net es lo suficientemente inteligente como para usar la misma referencia de memoria.Por lo tanto, el código no probar realmente la diferencia entre los dos concat métodos.

Prueba de esto en el tamaño:

Stopwatch s = new Stopwatch();

int n = 1000000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0, sbElapsedMilliseconds = 0, sbElapsedTicks = 0;

Random random = new Random(DateTime.Now.Millisecond);

string result;
s.Start();
for (var i = 0; i < n; i++)
    result = (random.Next().ToString() + " " + random.Next().ToString());
s.Stop();
cElapsedMilliseconds = s.ElapsedMilliseconds;
cElapsedTicks = s.ElapsedTicks;
s.Reset();

s.Start();
for (var i = 0; i < n; i++)
    result = string.Format("{0} {1}", random.Next().ToString(), random.Next().ToString());
s.Stop();
fElapsedMilliseconds = s.ElapsedMilliseconds;
fElapsedTicks = s.ElapsedTicks;
s.Reset();

StringBuilder sb = new StringBuilder();
s.Start();
for(var i = 0; i < n; i++){
    sb.Clear();
    sb.Append(random.Next().ToString());
    sb.Append(" ");
    sb.Append(random.Next().ToString());
    result = sb.ToString();
}
s.Stop();
sbElapsedMilliseconds = s.ElapsedMilliseconds;
sbElapsedTicks = s.ElapsedTicks;
s.Reset();

Console.WriteLine(n.ToString() + " x result = string.Format(\"{0} {1}\", p.FirstName, p.LastName); took: " + (fElapsedMilliseconds) + "ms - " + (fElapsedTicks) + " ticks");
Console.WriteLine(n.ToString() + " x result = (p.FirstName + \" \" + p.LastName); took: " + (cElapsedMilliseconds) + "ms - " + (cElapsedTicks) + " ticks");
Console.WriteLine(n.ToString() + " x sb.Clear();sb.Append(random.Next().ToString()); sb.Append(\" \"); sb.Append(random.Next().ToString()); result = sb.ToString(); took: " + (sbElapsedMilliseconds) + "ms - " + (sbElapsedTicks) + " ticks");
Console.WriteLine("****************");
Console.WriteLine("Press Enter to Quit");
Console.ReadLine();

Ejemplo De Salida:

1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 513ms - 1499816 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 393ms - 1150148 ticks
1000000 x sb.Clear();sb.Append(random.Next().ToString()); sb.Append(" "); sb.Append(random.Next().ToString()); result = sb.ToString(); took: 405ms - 1185816 ticks

Lástima los pobres traductores

Si saber su aplicación va a permanecer en inglés, entonces está bien, guardar el reloj hace tictac.Sin embargo, muchas culturas se suele ver Lastname Firstname, por ejemplo, en las direcciones.

Así que utilice string.Format(), especialmente si usted va a tener nunca la aplicación ir a cualquier lugar que el inglés no es su primer idioma.

Aquí están mis resultados de más de 100.000 iteraciones:

Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took (avg): 0ms - 689 ticks
Console.WriteLine(p.FirstName + " " + p.LastName); took (avg): 0ms - 683 ticks

Y aquí es el banco de código:

Stopwatch s = new Stopwatch();

var p = new { FirstName = "Bill", LastName = "Gates" };

//First print to remove the initial cost
Console.WriteLine(p.FirstName + " " + p.LastName);
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

int n = 100000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;

for (var i = 0; i < n; i++)
{
    s.Start();
    Console.WriteLine(p.FirstName + " " + p.LastName);
    s.Stop();
    cElapsedMilliseconds += s.ElapsedMilliseconds;
    cElapsedTicks += s.ElapsedTicks;
    s.Reset();
    s.Start();
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
    s.Stop();
    fElapsedMilliseconds += s.ElapsedMilliseconds;
    fElapsedTicks += s.ElapsedTicks;
    s.Reset();
}

Console.Clear();

Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took (avg): " + (fElapsedMilliseconds / n) + "ms - " + (fElapsedTicks / n) + " ticks");
Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took (avg): " + (cElapsedMilliseconds / n) + "ms - " + (cElapsedTicks / n) + " ticks");

Así que, no sé, cuya respuesta a la marca como una respuesta :)

La concatenación de cadenas es buena en un escenario simple como eso - es más complicado con algo más complicado que eso, incluso LastName, FirstName.Con el formato que usted puede ver, de un vistazo, lo que la estructura final de la cadena al leer el código, con la concatenación, se vuelve casi imposible discernir inmediatamente el resultado final (excepto con un ejemplo muy simple como este).

Lo que significa que en el largo plazo es que cuando vuelves a hacer un cambio en el formato de cadena, usted tendrá la capacidad de pop y hacer un par de ajustes en la cadena de formato, o de la arruga de su frente y empieza a moverse, todos los tipos de descriptores de acceso mezclado con el texto, que es más probable para introducir a los problemas.

Si usted está usando .NET 3.5 se puede utilizar un método de extensión como este y un fácil fluir, improvisando una sintaxis como esta:

string str = "{0} {1} is my friend. {3}, {2} is my boss.".FormatWith(prop1,prop2,prop3,prop4);

Finalmente, como la aplicación crece en complejidad, usted puede decidir que, para mantener la cordura cadenas en su aplicación que desea mover en un archivo de recursos para localizar o simplemente en un auxiliar estática.Esto será MUCHO más fácil de alcanzar si se han utilizado constantemente formatos, y su código puede ser simplemente refactorizado para usar algo como

string name = String.Format(ApplicationStrings.General.InformalUserNameFormat,this.FirstName,this.LastName);

Por muy simple manipulación que haría uso de la concatenación, pero una vez que usted consiga más allá de 2 o 3 elementos de Formato se vuelve más apropiado de la OMI.

Otra razón para preferir la Cadena.El formato es eso .NET cadenas son inmutables y haciendo de esta manera crea menos temporal/copias intermedias.

Mientras estoy totalmente de entender la preferencia de estilo y recogió la concatenación de mi primera respuesta, en parte basado en mi propia preferencia, parte de mi decisión se basó en la idea de que la concatenación sería más rápido.Así, por curiosidad, he probado y los resultados fueron sorprendentes, especialmente para una pequeña cadena.

Usar el siguiente código:

    System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();

    var p = new { FirstName = "Bill", LastName = "Gates" };

    s.Start();
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
    s.Stop();
    Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took: " + s.ElapsedMilliseconds + "ms - " + s.ElapsedTicks + " ticks");

    s.Reset();
    s.Start();
    Console.WriteLine(p.FirstName + " " + p.LastName);
    s.Stop();

    Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took: " + s.ElapsedMilliseconds + "ms - " + s.ElapsedTicks + " ticks");

Tengo los siguientes resultados:

Bill Gates
Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took: 2ms - 7280 ticks
Bill Gates
Console.WriteLine(p.FirstName + " " + p.LastName); took: 0ms - 67 ticks

Utilizando el método de formato es más de 100 veces más lento!!Concatenación ni siquiera registro de 1 ms, que es el motivo de la salida del temporizador de paso así.

Básicos para la concatenación de cadenas, generalmente se usa el segundo estilo más fácil de leer y más simple.Sin embargo, si yo estoy haciendo una más complicada cadena de combinación yo suelo optar por Cadena.Formato.

De la cadena.Formato guarda en un montón de ofertas y ventajas...

Console.WriteLine("User {0} accessed {1} on {2}.", user.Name, fileName, timestamp);
vs
Console.WriteLine("User " + user.Name + " accessed " + fileName + " on " + timestamp + ".");

Sólo un par de charicters guardado, pero creo que, en este ejemplo, el formato hace que sea mucho más limpio.

Un mejor prueba sería ver a su memoria mediante el monitor de Rendimiento, y el CLR contadores de memoria.Mi entendimiento es que la razón por la que desea utilizar de la Cadena.Formato en lugar de sólo la concatenación de cadenas es, ya que las cadenas son inmutables, que son sobrecargar innecesariamente el recolector de basura con cadenas temporales que deben ser recuperados en el paso siguiente.

StringBuilder y Cadena.Formato, aunque potencialmente más lento, más eficiente de la memoria.

¿Qué tiene de malo la concatenación de cadenas?

En general prefiero la antigua, especialmente cuando las cadenas de obtener una larga puede ser mucho más fácil de leer.

El otro beneficio es que creo que es uno de rendimiento, ya que este último realiza 2 cadena de creación de las declaraciones antes de pasar a la final de la cadena para la Consola.Método de la escritura.De la cadena.Formato utiliza un StringBuilder debajo de las mantas creo, por lo que varias concatenaciones se evitan.

Sin embargo, conviene señalar que si los parámetros que se pasan en Cadena.Formato (y otros métodos como el de la Consola.Escribir) son tipos de valor, a continuación, que serán empacados antes de que pasa, que puede proporcionar sus propios golpes de rendimiento. Entrada en el Blog sobre esto aquí.

Una semana a partir de ahora Ago 19, 2015, esta pregunta va a ser exactamente siete (7) años de edad.Ahora hay una mejor manera de hacer esto. Mejor en términos de mantenimiento que no me he hecho ninguna prueba de rendimiento en comparación con sólo la concatenación de cadenas (pero no importa en estos días?un par de milisegundos de diferencia?).La nueva forma de hacerlo con C# 6.0:

var p = new { FirstName = "Bill", LastName = "Gates" };
var fullname = $"{p.FirstName} {p.LastName}";

Esta nueva característica es mejor, La OMI, y en realidad mejor en nuestro caso como hemos códigos de donde podemos construir cadenas de consulta cuyo valor depende de algunos factores.Imagina un querystring donde tenemos 6 argumentos.Así que en lugar de hacer una, por ejemplo:

var qs = string.Format("q1={0}&q2={1}&q3={2}&q4={3}&q5={4}&q6={5}", 
    someVar, anotherVarWithLongName, var3, var4, var5, var6)

en puede ser escrito como este y es más fácil de leer:

var qs=$"q1={someVar}&q2={anotherVarWithLongName}&q3={var3}&q4={var4}&q5={var5}&q6={var6}";

A partir de C# 6.0 interpolados cadenas puede utilizarse para hacer esto, lo que simplifica el formato aún más.

var name = "Bill";
var surname = "Gates";
MessageBox.Show($"Welcome to the show, {name} {surname}!");

Un interpolados expresión de cadena que se parece a una cadena de plantilla que contiene expresiones.Un interpolados expresión de cadena que se crea una cadena mediante la sustitución de las expresiones con el método ToString represenations de las expresiones de los resultados.

Interpolados cadenas tienen un rendimiento similar al de la Cadena.Formato, pero mejora la legibilidad y la sintaxis más corta, debido al hecho de que los valores y las expresiones se insertan en línea.

Por favor, consulte también este artículo dotnetperls en la interpolación de cadenas.

Si usted está buscando un método por defecto para el formato de las cadenas, esto tiene sentido en términos de legibilidad y el rendimiento (excepto si microsegundos va a hacer una diferencia en su caso de uso específico).

  1. El formato es el ".NET" forma de hacerlo.Ciertas herramientas de refactorización (Refactorizar!para uno) incluso proponer a refactorizar el concat estilo de código para utilizar el estilo de formato.
  2. El formato es más fácil de optimizar para el compilador (aunque el segundo probablemente ser refactorizado para usar la "Concat" método rápido).
  3. El formato suele ser más claro para leer (sobre todo con "fancy" de formato).
  4. Formato de medios implícito llamadas a '.ToString' en todas las variables, lo cual es bueno para mejorar la legibilidad.
  5. De acuerdo a "la eficacia de la C#", el .NET "WriteLine" y "Formato" de las implementaciones están en mal estado, que autobox todos los tipos de valor (que es malo)."La eficacia de la C#", aconseja para llevar a cabo".ToString' se refiere de forma explícita, que en mi humilde opinión es falsa (ver Jeff publicación)
  6. Por el momento, el formato de tipo de sugerencias no son verificadas por el compilador, lo que resulta en errores de tiempo de ejecución.Sin embargo, esto podría ser modificado en futuras versiones.

Me gustaría uso de la Cadena.Formato, pero me gustaría tener también la cadena de formato en los archivos de recursos por lo que puede ser localizada para otros idiomas.El uso de una simple cadena de concat no te permite hacer eso.Obviamente, si usted no siempre se necesita localizar esa cadena, esta no es una razón para pensar.Realmente depende de lo que la cadena se para.

Si va a ser mostrado al usuario, yo uso la Cadena.Formato para que yo pueda localizar si me necesita - y FxCop se corrector ortográfico para mí, por si acaso :)

Si contiene números o cualquier otra cadena que no son cosas (por ejemplo,las fechas), yo uso la Cadena.Formato porque me da más control sobre el formato.

Si es para la construcción de una consulta como SQL, yo uso la Linq.

Si para la concatenación de cadenas de caracteres dentro de un bucle, yo uso la StringBuilder para evitar problemas de rendimiento.

Si es para alguna salida que el usuario no ve, y no va a efecto de rendimiento yo uso la Cadena.Formato porque estoy en el hábito de usar de todos modos y sólo estoy acostumbrado :)

Si usted está tratando con algo que debe ser fácil de leer (y este es el código de la mayoría), me gustaría seguir con la sobrecarga de operadores versión a MENOS que:

  • El código debe ser ejecutado millones de veces
  • Usted está haciendo toneladas de concats (más de 4 es de una tonelada)
  • El código está dirigido hacia el Compact Framework

En al menos dos de estas circunstancias, se debería usar StringBuilder en su lugar.

Yo elija en base a la legibilidad.Yo prefiero la opción de formato cuando hay algún texto en torno a las variables.En este ejemplo:

Console.WriteLine("User {0} accessed {1} on {2}.", 
                   user.Name, fileName, timestamp);

entender el significado, incluso sin los nombres de las variables, mientras que la concat está lleno de citas y + signos y confunde a mis ojos:

Console.WriteLine("User " + user.Name + " accessed " + fileName + 
                  " on " + timestamp + ".");

(Me prestaron Mike ejemplo, porque me gusta)

Si la cadena de formato no significa mucho, sin los nombres de las variables, tengo que usar concat:

   Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

La opción de formato me hace leer los nombres de las variables y asignarlos a los números correspondientes.La concat opción no requiere que.Todavía estoy confundido por las citas y + signos, pero la alternativa es peor.Ruby?

   Console.WriteLine(p.FirstName + " " + p.LastName);

El rendimiento sabio, espero que el formato de opción a ser más lento que la concat, ya que el formato requiere de la cadena ser analiza.Yo no recuerdo haber para optimizar este tipo de instrucción, pero si lo hiciera, me gustaría mirar string métodos como Concat() y Join().

La otra ventaja del formato es que la cadena de formato se puede poner en un archivo de configuración.Muy práctico con los mensajes de error de la interfaz de usuario de texto.

Si usted tiene la intención de localizar el resultado, luego de Cadena.El formato es esencial, ya que los diferentes lenguajes naturales incluso podría no tener los datos en el mismo orden.

Creo que esto depende mucho de la complejidad de la salida es.Tiendo a elegir el escenario que funciona mejor en el momento.

Escoger la herramienta correcta basada en el trabajo :D Lo que se ve más limpio!

Yo prefiero la segunda, pero no tengo argumentos racionales en este momento para apoyar esa posición.

Interesante!

Acaba de agregar

        s.Start();
        for (var i = 0; i < n; i++)
            result = string.Concat(p.FirstName, " ", p.LastName);
        s.Stop();
        ceElapsedMilliseconds = s.ElapsedMilliseconds;
        ceElapsedTicks = s.ElapsedTicks;
        s.Reset();

Y es incluso más rápido (supongo que de la cadena.Concat se llama en ambos ejemplos, pero el primero que se requiere de algún tipo de traducción).

1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 249ms - 3571621 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 65ms - 944948 ticks
1000000 x result = string.Concat(p.FirstName, " ", p.LastName); took: 54ms - 780524 ticks

Ya que no creo que las respuestas aquí abarcar todo, me gustaría hacer un pequeño aporte aquí.

Console.WriteLine(string format, params object[] pars) llamadas string.Format.El '+' implica la concatenación de cadenas.No creo que esto siempre tiene que ver con el estilo;Yo tiendo a mezclar los dos estilos en función del contexto en que me encuentre.

Respuesta corta

La decisión que usted está enfrentando tiene que ver con la cadena de distribución.Voy a tratar de hacer que sea sencillo.

Dicen que usted tiene

string s = a + "foo" + b;

Si se ejecuta este, se evaluará de la siguiente manera:

string tmp1 = a;
string tmp2 = "foo" 
string tmp3 = concat(tmp1, tmp2);
string tmp4 = b;
string s = concat(tmp3, tmp4);

tmp aquí no es realmente una variable local, pero es temporal para el JIT (es empujado en la IL de la pila).Si usted empuja una cadena en la pila (como ldstr en la IL de los literales), poner una referencia a un puntero de cadena en la pila.

En el momento que usted llame concat esta referencia se convierte en un problema, porque no hay ninguna cadena de referencia que contiene a las dos cadenas.Esto significa que .NET tiene que asignar un nuevo bloque de memoria, y luego llenarlo con las dos cadenas.La razón de esto es un problema, es debido a que la asignación es relativamente caro.

Lo que cambia la pregunta:¿Cómo se puede reducir el número de concat las operaciones?

Así, la respuesta aproximada es: string.Format para >1 concats, '+' funcionará muy bien para 1 concat.Y si no se preocupan por hacer micro-optimizaciones de rendimiento, string.Format funcionarán igual de bien, en el caso general.

Una nota acerca de la Cultura

Y luego hay algo que se llama cultura...

string.Format permite utilizar CultureInfo en su formato.Un simple operador '+' usos de la cultura actual.

Esto es especialmente una observación importante si usted está escribiendo formatos de archivo y f.ex. double valores que en "añadir" para una cadena.En máquinas diferentes, usted podría terminar con diferentes cadenas si no uso string.Format con una explícita CultureInfo.

F. ex.considere lo que sucede si cambia un '.' una ',' al escribir su coma-separados-archivo de valores...en holanda el separador de decimales es la coma, por lo que el usuario podría obtener una 'gracia' sorpresa.

Más detallada respuesta

Si usted no sabe el tamaño exacto de la cadena de antemano, es mejor utilizar una política como esta para overallocate los búferes de utilizar.La holgura de espacio está lleno de primero, después de que los datos se copian en.

Crecimiento significa la asignación de un nuevo bloque de memoria y copiar los datos al nuevo buffer.El antiguo bloque de memoria puede ser puesto en libertad.Usted obtener la línea de fondo a este punto:el crecimiento es una operación costosa.

La forma más práctica de hacer esto es utilizar una sobreasignación de la política.La más común es la política de overallocate búferes en potencias de 2.Por supuesto, usted tiene que hacerlo un poco más inteligente de lo que (ya que no tiene sentido para crecer a partir de 1,2,4,8 si usted ya sabe que necesita 128 caracteres), pero usted consigue el cuadro.La directiva asegura que no necesita demasiado muchas de las costosas operaciones que he descrito anteriormente.

StringBuilder es una clase que básicamente overallocates subyacente de búfer en potencias de dos. string.Format utiliza StringBuilder bajo el capó.

Esto hace que su decisión básica de trade-off entre overallocate-y-append (múltiple) (w/w.o.cultura) o simplemente de asignar-y-append.

Personalmente, la segunda como todo lo que se utiliza está en el orden directa será de salida en.Mientras que con la primera tiene que coincidir con la {0} y {1} con la adecuada var, que es fácil echar a perder.

Al menos no es tan malo como el C++ sprintf donde si se obtiene el tipo de variable mal la cosa va a explotar.

También, desde la segunda es todo en línea y no tiene que hacer cualquier búsqueda y reemplazo para todos los {0} cosas, esta debe ser más rápido...aunque no lo sé seguro.

De hecho, me gusta el primero, porque cuando hay un montón de variables entremezclado con el texto parece más fácil de leer para mí.Además, es más fácil lidiar con las cotizaciones cuando el uso de la cadena.Format(), uh, formato.Aquí es digno de análisis de la concatenación de cadenas.

Siempre he ido de la cadena.Format() de la ruta.Ser capaz de almacenar los formatos en variables como la de Nathan ejemplo es una gran ventaja.En algunos casos puede añadir una variable, pero una vez más de 1 variable se concatenan me refactorizar para utilizar el formato.

Ah, y para la integridad, el siguiente es un par de garrapatas más rápido de lo normal concatenación:

Console.WriteLine(String.Concat(p.FirstName," ",p.LastName));

La primera de ellas (formato) se ve mejor para mí.Es más legible y no está creando extra temporal de los objetos string.

Yo estaba curioso donde StringBuilder puso de pie con estas pruebas.Resultados a continuación...

class Program {
   static void Main(string[] args) {

      var p = new { FirstName = "Bill", LastName = "Gates" };

      var tests = new[] {
         new { Name = "Concat", Action = new Action(delegate() { string x = p.FirstName + " " + p.LastName; }) },
         new { Name = "Format", Action = new Action(delegate() { string x = string.Format("{0} {1}", p.FirstName, p.LastName); }) },
         new { Name = "StringBuilder", Action = new Action(delegate() {
            StringBuilder sb = new StringBuilder();
            sb.Append(p.FirstName);
            sb.Append(" ");
            sb.Append(p.LastName);
            string x = sb.ToString();
         }) }
      };

      var Watch = new Stopwatch();
      foreach (var t in tests) {
         for (int i = 0; i < 5; i++) {
            Watch.Reset();
            long Elapsed = ElapsedTicks(t.Action, Watch, 10000);
            Console.WriteLine(string.Format("{0}: {1} ticks", t.Name, Elapsed.ToString()));
         }
      }
   }

   public static long ElapsedTicks(Action ActionDelg, Stopwatch Watch, int Iterations) {
      Watch.Start();
      for (int i = 0; i < Iterations; i++) {
         ActionDelg();
      }
      Watch.Stop();
      return Watch.ElapsedTicks / Iterations;
   }
}

Resultados:

Concat: 406 ticks
Concat: 356 ticks
Concat: 411 ticks
Concat: 299 ticks
Concat: 266 ticks
Format: 5269 ticks
Format: 954 ticks
Format: 1004 ticks
Format: 984 ticks
Format: 974 ticks
StringBuilder: 629 ticks
StringBuilder: 484 ticks
StringBuilder: 482 ticks
StringBuilder: 508 ticks
StringBuilder: 504 ticks

De acuerdo a la CMDS de preparación de material, Microsoft sugiere utilizar el operador + cuando se trata de un número muy pequeño de concatenaciones (probablemente 2 a 4).Todavía no estoy seguro de por qué, pero es algo a tener en cuenta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top