Como no creo que las respuestas aquí cubran todo, me gustaría hacer una pequeña adición aquí.
Console.WriteLine(string format, params object[] pars)
llamadas string.Format
. El '+' implica concatenación de cadenas. No creo que esto siempre tenga que ver con el estilo; Tiendo a mezclar los dos estilos dependiendo del contexto en el que me encuentre.
Respuesta corta
La decisión que enfrenta tiene que ver con la asignación de cadenas. Trataré de hacerlo simple.
Di que tienes
string s = a + "foo" + b;
Si ejecuta esto, 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 (se inserta en la pila IL). Si empuja una cadena en la pila (como ldstr
en IL para literales), coloca una referencia a un puntero de cadena en la pila.
El momento en que llama a concat
esta referencia se convierte en un problema, porque no hay ninguna referencia de cadena disponible que contenga ambas cadenas. Esto significa que .NET necesita asignar un nuevo bloque de memoria y luego llenarlo con las dos cadenas. La razón por la que esto es un problema es porque la asignación es relativamente costosa.
Lo que cambia la pregunta a: ¿Cómo puede reducir el número de concat
operaciones?
Entonces, la respuesta aproximada es: string.Format
para> 1 concats, '+' funcionará bien para 1 concat. Y si no te importa hacer optimizaciones de micro rendimiento, string.Format
funcionará bien en el caso general.
Una nota sobre cultura
Y luego hay algo llamado cultura ...
string.Format
le permite usar CultureInfo
en su formato. Un operador simple '+' usa la cultura actual.
Esto es especialmente un comentario importante si está escribiendo formatos de archivo y f.ex. double
valores que 'agrega' a una cadena. En diferentes máquinas, puede terminar con diferentes cadenas si no lo usa string.Format
con un explícito CultureInfo
.
F.ex. considere lo que sucede si cambia un '.' para un ',' mientras escribe su archivo de valores separados por comas ... en holandés el separador decimal es una coma, por lo que su usuario podría recibir una sorpresa 'divertida'.
Respuesta más detallada
Si no conoce el tamaño exacto de la cadena de antemano, es mejor usar una política como esta para sobreasignar los búferes que usa. El espacio flojo se llena primero, después de lo cual se copian los datos.
Crecer significa asignar un nuevo bloque de memoria y copiar los datos antiguos al nuevo búfer. El antiguo bloque de memoria se puede liberar. En este punto se obtiene el resultado final: el crecimiento es una operación costosa.
La forma más práctica de hacerlo es utilizar una política de sobreasignación. La política más común es sobreasignar buffers en potencias de 2. Por supuesto, debe hacerlo un poco más inteligente que eso (ya que no tiene sentido crecer de 1,2,4,8 si ya sabe que necesita 128 caracteres) ) pero te haces una idea. La política garantiza que no necesita muchas de las costosas operaciones que describí anteriormente.
StringBuilder
es una clase que básicamente sobreasigna el búfer subyacente en potencias de dos. string.Format
usos StringBuilder
debajo del capó.
Esto hace que su decisión sea una compensación básica entre sobreasignar y agregar (-múltiple) (sin cultura) o simplemente asignar-y-agregar.
string.Format
que no utiliza ninguna función de formato compuesto (es decir, simple{0}
) y reemplazarla con la concatenación de cadenas considerablemente más rápida. Me pregunto que tal hazaña se pueda lograr con una reescritura IL existente como PostSharp.