2008-12-08 9 views
50

Un reciente question came up sobre el uso de String.Format(). Parte de mi respuesta incluía una sugerencia para usar StringBuilder.AppendLine (string.Format (...)). Jon Skeet sugirió que este era un mal ejemplo y propuso usar una combinación de AppendLine y AppendFormat.¿Cuándo utiliza StringBuilder.AppendLine/string.Format vs. StringBuilder.AppendFormat?

Se me ocurrió que nunca me había acostumbrado a un enfoque "preferido" para usar estos métodos. Creo que podría comenzar a usar algo como lo siguiente, pero estoy interesado en saber lo que otras personas utilizan como una "mejor práctica":

sbuilder.AppendFormat("{0} line", "First").AppendLine(); 
sbuilder.AppendFormat("{0} line", "Second").AppendLine(); 

// as opposed to: 

sbuilder.AppendLine(String.Format("{0} line", "First")); 
sbuilder.AppendLine(String.Format("{0} line", "Second")); 
+0

¿Quizás su ejemplo de código podría ilustrar ambos casos? :) – annakata

Respuesta

56

que ver AppendFormat seguido por AppendLine que no sólo es más fácil de leer, pero también más rendimiento inferior llamando al AppendLine(string.Format(...)).

Este último crea una cadena completamente nueva y luego la agrega al por mayor en el constructor existente. No voy a ir tan lejos como para decir "¿Por qué molestarse en usar StringBuilder entonces?" pero parece un poco en contra del espíritu de StringBuilder.

+0

Sí, voy a tomar todo esto en cuenta (y gracias por aceptarme en primer lugar, por cierto). –

+1

No hay problema, y ​​lo siento si mi tono parecía ronco en el comentario original. La multitarea me lo hace a veces :( –

0

AppendFormat() es mucho más fácil de leer que AppendLine (String.Format())

0

prefiero esta estructura:

sbuilder.AppendFormat("{0} line\n", "First"); 

Aunque es cierto que hay algo que decir acerca de la separación de la línea se rompe

+1

Supongo que "jinx" no funciona en SO, ¿o sí? – Coderer

+0

Solía ​​usar \ r \ n, pero prefiero Environment.NewLine que es incómodo de usar. Por lo tanto, hacer la pregunta –

0

¿Es sólo positivamente horrible simplemente usar

sbuilder.AppendFormat("{0} line\n", first); 

? Quiero decir, sé que no es independiente de la plataforma o lo que sea, pero en 9 de cada 10 casos hace el trabajo.

2

Si el rendimiento es importante, intente evitar AppendFormat() completamente. Use múltiples llamadas Append() o AppendLine() en su lugar. Esto hace que su código sea más grande y menos legible, pero es más rápido porque no se debe realizar un análisis de cadenas. El análisis de cadenas es más lento de lo que imagina.

generalmente uso:

sbuilder.AppendFormat("{0} line", "First"); 
sbuilder.AppendLine(); 
sbuilder.AppendFormat("{0} line", "Second"); 
sbuilder.AppendLine(); 

A menos que el rendimiento es fundamental, en cuyo caso me gustaría usar:

sbuilder.Append("First"); 
sbuilder.AppendLine(" line"); 
sbuilder.Append("Second"); 
sbuilder.AppendLine(" line"); 

(Por supuesto, esto tendría más sentido si "primero" y " Segundo "donde no literales de cadena"

+0

¿Cuál es su prueba del mal rendimiento de AppendFormat? –

+0

El índice de referencia que obtuve mostró un aumento del rendimiento de 5 veces al usar llamadas anexadas separadas() en lugar de una sola llamada AppendFormat() con 4 argumentos. – Chris

11

String.format crea un objeto StringBuilder internamente. Al hacer

sbuilder.AppendLine(String.Format("{0} line", "First")); 

se crea una instancia adicional de generador de cadenas, con todos sus gastos generales.


reflector en mscorlib, Commonlauageruntimelibary, System.String.Format

public static string Format(IFormatProvider provider, string format, params object[] args) 
{ 
    if ((format == null) || (args == null)) 
    { 
     throw new ArgumentNullException((format == null) ? "format" : "args"); 
    } 
    StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8)); 
    builder.AppendFormat(provider, format, args); 
    return builder.ToString(); 
} 
11

Basta con crear un método de extensión.

public static StringBuilder AppendLine(this StringBuilder builder, string format, params object[] args) 
{ 
    builder.AppendFormat(format, args).AppendLine(); 
    return builder; 
} 

Razones yo prefiero esto:

  • no sufre tanta sobrecarga como AppendLine(string.Format(...)), como se indicó anteriormente.
  • Impide que olvide agregar la parte .AppendLine() al final (ocurre con la frecuencia suficiente).
  • Es más fácil de leer (pero eso es más que una opinión).

Si no le gusta que se llame 'AppendLine', puede cambiarlo a 'AppendFormattedLine' o lo que desee. Me gusta todo alineando con otras llamadas a 'AppendLine' sin embargo:

var builder = new StringBuilder(); 

builder 
    .AppendLine("This is a test.") 
    .AppendLine("This is a {0}.", "test"); 

Apenas añada uno de estos para cada uno de sobrecarga se utiliza el método de AppendFormat en StringBuilder.

Cuestiones relacionadas