¿Cuándo utiliza StringBuilder.AppendLine / string.Format vs. StringBuilder.AppendFormat?
-
20-08-2019 - |
Pregunta
Una reciente surgió una pregunta sobre el uso de String.Format (). Parte de mi respuesta incluyó 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.
Se me ocurrió que nunca me había acomodado en un " preferido " enfoque 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 usan como & Quot; mejor práctica & Quot ;:
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"));
Solución
Veo AppendFormat
seguido de AppendLine
como no solo más legible, sino también más eficaz que llamar a AppendLine(string.Format(...))
.
Este último crea una cadena completamente nueva y luego la agrega al por mayor en el generador 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.
Otros consejos
Simplemente cree 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 por las que prefiero esto:
- No sufre tanta sobrecarga como
AppendLine(string.Format(...))
, como se indicó anteriormente. - Evita que me olvide de agregar la parte
.AppendLine()
al final (sucede con bastante frecuencia). - Es más legible (pero eso es más una opinión).
Si no le gusta que se llame 'AppendLine', puede cambiarlo a 'AppendFormattedLine' o lo que desee. Sin embargo, disfruto todo alineado con otras llamadas a 'AppendLine':
var builder = new StringBuilder();
builder
.AppendLine("This is a test.")
.AppendLine("This is a {0}.", "test");
Simplemente agregue uno de estos por cada sobrecarga que use del método AppendFormat en StringBuilder.
String.format crea un objeto StringBuilder internamente. Al hacer
sbuilder.AppendLine( String.Format( "{0} line", "First"));
se crea una instancia adicional del 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();
}
Si el rendimiento es importante, intente evitar AppendFormat () por completo. Utilice 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 es necesario analizar las cadenas. El análisis de cadenas es más lento de lo que imaginas.
Generalmente uso:
sbuilder.AppendFormat("{0} line", "First");
sbuilder.AppendLine();
sbuilder.AppendFormat("{0} line", "Second");
sbuilder.AppendLine();
A menos que el rendimiento sea crítico, en cuyo caso usaría:
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 hay literales de cadena)
AppendFormat () es mucho más legible que AppendLine (String.Format ())
Prefiero esta estructura:
sbuilder.AppendFormat("{0} line\n", "First");
Aunque hay que admitir que hay algo que decir para separar los saltos de línea.
¿Es simplemente horrible usar simplemente
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.