Когда вы используете StringBuilder.AppendLine/string.Format против StringBuilder.AppendFormat?
Недавно возник вопрос об использовании String.Format(). Часть моего ответа включала предложение использовать StringBuilder.AppendLine(string.Format(...)). Джон Скит предположил, что это плохой пример, и предложил использовать комбинацию AppendLine и AppendFormat.
Мне пришло в голову, что я никогда не выбирал "предпочтительный" подход к использованию этих методов. Я думаю, что я мог бы начать использовать что-то вроде следующего, но мне интересно узнать, что другие люди используют в качестве "лучшей практики":
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"));
7 ответов
Я смотрю AppendFormat
с последующим AppendLine
как не только более читаемый, но и более производительный, чем вызывающий AppendLine(string.Format(...))
,
Последний создает совершенно новую строку, а затем добавляет ее оптом в существующего застройщика. Я не собираюсь заходить так далеко, чтобы сказать: "Зачем тогда использовать StringBuilder?" но это кажется немного против духа StringBuilder.
Просто создайте метод расширения.
public static StringBuilder AppendLine(this StringBuilder builder, string format, params object[] args)
{
builder.AppendFormat(format, args).AppendLine();
return builder;
}
Причины, по которым я предпочитаю это:
- Не страдает так много накладных расходов, как
AppendLine(string.Format(...))
, как указано выше. - Помешает мне забыть добавить
.AppendLine()
часть в конце (случается достаточно часто). - Это более читабельно (но это больше мнение).
Если вам не нравится, когда он называется "AppendLine", вы можете изменить его на "AppendFormattedLine" или что угодно. Мне нравится все, что совпадает с другими вызовами "AppendLine", хотя:
var builder = new StringBuilder();
builder
.AppendLine("This is a test.")
.AppendLine("This is a {0}.", "test");
Просто добавьте один из них для каждой перегрузки, которую вы используете для метода AppendFormat в StringBuilder.
String.format создает объект StringBuilder внутри. При выполнении
sbuilder.AppendLine( String.Format( "{0} line", "First"));
создается дополнительный экземпляр компоновщика строк со всеми его издержками.
Отражатель на 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();
}
Если важна производительность, старайтесь полностью избегать AppendFormat(). Вместо этого используйте несколько вызовов Append() или AppendLine(). Это делает ваш код больше и менее читабельным, но это быстрее, потому что не нужно разбирать строки. Разбор строк происходит медленнее, чем вы можете себе представить.
Я обычно использую:
sbuilder.AppendFormat("{0} line", "First");
sbuilder.AppendLine();
sbuilder.AppendFormat("{0} line", "Second");
sbuilder.AppendLine();
Если производительность не критична, в этом случае я бы использовал:
sbuilder.Append("First");
sbuilder.AppendLine(" line");
sbuilder.Append("Second");
sbuilder.AppendLine(" line");
(Конечно, это будет иметь больше смысла, если "Первый" и "Второй", где не строковые литералы)
AppendFormat() намного удобнее для чтения, чем AppendLine(String.Format())
Это просто ужасно просто использовать
sbuilder.AppendFormat("{0} line\n", first);
? Я имею в виду, я знаю, что он не зависит от платформы или что-то еще, но в 9 из 10 случаев он выполняет свою работу.
Я предпочитаю эту структуру:
sbuilder.AppendFormat("{0} line\n", "First");
Хотя, по общему признанию, есть кое-что, что нужно сказать для выделения разрывов строк.