Когда вы используете 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"));

возможно, ваш пример кода может проиллюстрировать оба случая? :)

annakata 08.12.2008 17:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
59
1
28 194
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

Я считаю, что AppendFormat, за которым следует AppendLine, не только более читаемый, но и более производительный, чем вызов AppendLine(string.Format(...)).

Последний создает целую новую строку, а затем добавляет ее оптом в существующий построитель. Я не собираюсь заходить так далеко, чтобы сказать: «Зачем тогда использовать StringBuilder?» но это кажется немного противоречащим духу StringBuilder.

Да, я полностью возьмусь за это (и, во-первых, спасибо, что взяли меня за это, BTW).

Neil Barnwell 08.12.2008 17:39

Нет проблем - и извините, если мой тон в исходном комментарии показался грубым. Иногда со мной так поступает многозадачность :(

Jon Skeet 08.12.2008 17:40

AppendFormat () намного читабельнее, чем AppendLine (String.Format ())

Я предпочитаю такую ​​структуру:

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

Хотя, по общему признанию, есть что сказать о разделении разрывов строк.

Я обычно использовал \ r \ n, но предпочитаю Environment.NewLine, который неудобно использовать. Отсюда возникает вопрос.

Neil Barnwell 09.12.2008 01:23

Просто ужасно просто использовать

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

? Я имею в виду, я знаю, что он не зависит от платформы или чего-то еще, но в 9 из 10 случаев он выполняет свою работу.

Если производительность важна, старайтесь полностью избегать 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");

(Конечно, это имело бы смысл, если бы "Первый" и "Второй" не были строковыми литералами)

Тест, который я сделал, показал 5-кратное увеличение производительности при использовании отдельных вызовов Append () вместо одного вызова AppendFormat () с 4 аргументами.

Chris 09.12.2008 12:47

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();
}

Просто создайте метод расширения.

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.

Другие вопросы по теме