string.format con variables vs variables en línea

9

¿Cuáles son los pros / contras (si los hay) para usar

string output; 
int i = 10;
output = string.Format("the int is {0}", i);

versus

string output; 
int i = 10;
output = "the int is " + i;

Siempre he usado el último ejemplo, pero parece que una buena mayoría de los tutoriales en línea usan el ejemplo string.format. No creo que haya diferencias reales en términos de eficiencia, mi pensamiento inicial es que un codificador no tiene que seguir rompiendo la cadena para insertar variables.

Jim
fuente
8
La razón principal es que hace que la traducción sea mucho más fácil, porque su programa no necesita comprender la forma en que los diferentes idiomas construyen sus oraciones. Por ejemplo, muchas expresiones y frases en francés son opuestas en comparación con sus traducciones al inglés.
JohnL

Respuestas:

22

Si considera que la traducción es importante en su proyecto, la primera sintaxis realmente lo ayudará.

Por ejemplo, puede tener:

static final string output_en = "{0} is {1} years old.";
static final string output_fr = "{0} a {1} ans.";

int age = 10;
string name = "Henri";
System.out.println(string.Format(output_en, name, age));
System.out.println(string.Format(output_fr, name, age));

También tenga en cuenta que sus variables pueden no estar siempre en el mismo lugar en la oración con esa sintaxis:

static final string output_yoda = "{1} years {0} has.";
Alex García
fuente
44
+1 por usar Yoda-speak como ejemplo de sintaxis objeto-sujeto-verbo.
Mike Harris
1
Con C # tenemos una nueva opción:System.out.println($"{name} is {age} year's old.");
Berin Loritsch
@BerinLoritsch: desafortunadamente, es completamente inutilizable para la localización.
Bryan Boettcher
@BryanBoettcher, entendido, pero no vi nada en el OP que dijera que eso era lo que intentaban lograr.
Berin Loritsch
8

Vea la primera respuesta para /programming/4671610/why-use-string-format . En mi opinión, cubre todo por qué es mejor.

Además, cada ensamblado .NET tiene un grupo interno, que contiene una colección de cadenas únicas. Cuando se compila su código, todos los literales de cadena a los que hace referencia en su código se agregan a este grupo. Si tiene un código que se ve así:

"the int is " + i + " and the double is " + d

Eso lo hace 2 cuerdas en la piscina.

Si usted tiene:

"the int is {0} and the double is {1}"

Solo tienes una cadena en el grupo.

Es un poco más complicado saber cuándo los Strings están internados y cuándo no porque el compilador tiene cierta inteligencia al detectar Strings que a veces no necesitan ser internados ... Consulte, por ejemplo, este artículo que brinda más información sobre esto importar.

Editar: después de desenterrar un poco, he encontrado una respuesta interesante a la pregunta ¿ Cuándo es mejor usar String.Format vs cadena de concatenación? . En resumen, el autor de la respuesta con +30 votos hace un argumento convincente a favor de la concatenación de cadenas cuando la localización no está involucrada.

Jalayn
fuente
2
Creo también, estilísticamente, que resuena con las personas, es decir, personas como yo, que están acostumbradas a imprimir y correr desde c.
Jonathan Henson el
Me hubiera gustado saber por qué el voto negativo para arreglar mi respuesta. Gracias.
Jalayn
4

Prefiero la primera manera porque me permite ver con precisión cómo se verá la cadena cuando salga. Es muy fácil olvidarse de agregar un espacio, o agregar un espacio extra cuando se agregan cadenas.

Estoy seguro de que también hay un beneficio de rendimiento en la primera forma debido a que no tiene que crear las cadenas adicionales; Pero esa no es mi principal preocupación.

John Kraft
fuente
2

Al usar la primera opción, puede almacenar una cadena de formato de uso común y reducir la escritura necesaria y facilitar la actualización de la cadena en todos los lugares donde se usa. Básicamente, la primera opción permite que DRY se implemente fácilmente. También es una sintaxis mucho mejor si es necesario utilizar múltiples variables en una cadena, como usted mencionó.

Ryathal
fuente
ahh ya veo, supongo que no pensé en el ejemplo: string.format ("el int es {0}. de nuevo es {0}", int);
Jim
1

Creo string.Format()que es más fácil ver cuál será exactamente el resultado (para que no tenga problemas con espacios olvidados o algo así), y también es más fácil de escribir y modificar.

Si desea hacer un formateo muy simple, usar el +operador más podría ser más fácil, pero tiendo a usarlo solo cuando concatene dos cadenas, no más.

Para mostrar cómo string.Format()es más fácil de modificar, considere que desea agregar un punto final al final de la oración en su ejemplo: ir de string.Format("The int is {0}", i)a string.Format("The int is {0}.", i)es solo un carácter. Pero pasar de "the int is " + ia "the int is " + i + '.'es mucho más.

Otra ventaja de esto string.Format()es que le permite especificar fácilmente el formato a usar, como string.Format("The int is 0x{0:X}.", i). Esto es aún más importante al formatear la fecha.

En cuanto a la eficiencia, string.Format()lo más probable es que sea más lento que las simples concatenaciones de cadenas. Pero es probable que un código como este no esté en una ruta activa, por lo que no importa. Y si lo hace, probablemente sea mejor usarlo StringBuilder.

svick
fuente
string.Format utiliza internamente un StringBuilder de todos modos
Bryan Boettcher
1

Use el que hace que su código sea más legible. No te preocupes por el rendimiento.

Para su ejemplo a continuación, prefiero B porque es más legible. Pero las traducciones de idiomas anteriores también tienen sentido. No dejes que nadie te obligue a usar cadenas. Formate, en su lugar, lee y señala el excelente blog de Jeff Atwoods en The Sad Tragedy of Micro Optimizations Theater

UNA:

string output; 
int i = 10;
output = string.Format("the int is {0}", i);

versus

SI:

string output; 
int i = 10;
output = "the int is " + i;
Makach
fuente
-1

Ref: Salida de cadena: ¿formato o concat en C #?

Considera este código.

Es una versión ligeramente modificada de su código.

  1. Eliminé Console.WriteLine, ya que probablemente sea un orden de magnitud más lento que el que estoy tratando de medir.
  2. Estoy mirando el cronómetro antes del ciclo y lo detengo justo después, de esta manera no pierdo precisión si la función toma, por ejemplo, 26,4 ticks para ejecutarse.
  3. La forma en que dividió el resultado por número de iteraciones fue incorrecta. Vea qué sucede si tiene 1000 milisegundos y 100 milisegundos. En ambas situaciones, obtendrá 0 ms después de dividirlo 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 result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 618ms - 2213706 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 166ms - 595610 ticks
jp2code
fuente
1
¿Cómo responde esto a los aspectos de si el primer ejemplo de código o el segundo ejemplo de código es un mejor diseño? ¿Cómo cuenta medio segundo más de 1M de iteraciones si este es un código más fácil de mantener para una persona o no?
Jim preguntó: "¿Cuáles son los pros y los contras?" Esto muestra que en muchas iteraciones, String.Format es más rápido.
jp2code
Debería considerar agregarlo completamente a su respuesta en lugar de dejarlo como un bloque de código y diferencias con el código del OP. Tal como está, su respuesta no responde la pregunta del OP en inglés. Mira las otras respuestas. Sería posible eliminar todo el código de ellos y aún así tener una respuesta a la pregunta del OP.