string.format с переменными против встроенных переменных


9

Каковы плюсы / минусы (если таковые имеются) для использования

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

против

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

Я всегда использовал последний пример, но кажется, что большинство онлайн-уроков используют пример string.format. Я не думаю, что есть какие-то реальные различия с точки зрения эффективности, моя первоначальная мысль такова, что программисту не нужно постоянно ломать строку, чтобы вставить переменные.


8
Основная причина в том, что это делает перевод намного проще, потому что вашей программе не нужно понимать, как разные языки строят свои предложения. Например, многие выражения и фразы на французском языке являются задними по сравнению с их английскими переводами.
JohnL

Ответы:


22

Если вы считаете, что перевод важен в вашем проекте, первый синтаксис действительно поможет в этом.

Например, вы можете иметь:

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

Также обратите внимание, что ваши переменные могут не всегда находиться в одном и том же месте в предложении с этим синтаксисом:

static final string output_yoda = "{1} years {0} has.";

4
+1 за использование языка йода в качестве примера синтаксиса объект-субъект-глагол.
Майк Харрис

1
С C # у нас есть новая опция:System.out.println($"{name} is {age} year's old.");
Берин Loritsch


@BerinLoritsch: к сожалению, он совершенно непригоден для локализации.
Брайан

@BryanBoettcher, понял, но я не видел ничего в ОП, говорящего, что это то, что они пытались достичь.
Берин Лорич

8

Проверьте первый ответ для /programming/4671610/why-use-string-format . Это охватывает все, на мой взгляд, почему это лучше.

Кроме того, каждая сборка .NET имеет внутренний пул, содержащий коллекцию уникальных строк. Когда ваш код скомпилирован, все строковые литералы, на которые вы ссылаетесь в своем коде, добавляются в этот пул. Если у вас есть код, который выглядит так:

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

Это делает его 2 струнами в бассейне.

Если у тебя есть:

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

У вас есть только одна строка в бассейне.

Немного сложнее узнать, когда строки интернированы, а когда нет, потому что компилятор обладает некоторым интеллектом при обнаружении строк, которые, возможно, не требуют интернирования иногда ... Посмотрите, например, эту статью, которая дает более полное представление об этом дело.

Редактировать: после того, как я немного покопался , я столкнулся с интересным ответом на вопрос: когда лучше использовать String.Format против конкатенации строк? , Короче говоря, автор ответа с +30 голосами приводит убедительный аргумент в пользу объединения строк, когда локализация не задействована.


2
Я думаю также, стилистически, это находит отклик у людей, то есть таких, как я, которые привыкли печатать и спринтовать из c.
Джонатан Хенсон

Я хотел бы знать, почему понизить голос, чтобы исправить мой ответ. Спасибо.
Джалайн

4

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

Я уверен, что в первом случае есть и выигрыш в производительности, так как нет необходимости создавать дополнительные строки; но это не моя главная задача.


2

Используя первую опцию, вы можете сохранить обычно используемую строку формата и сократить объем ввода, необходимый для упрощения обновления строки везде, где она используется. По сути, первый вариант позволяет легко реализовать DRY. Это также намного более приятный синтаксис, если в строке нужно использовать несколько переменных, как вы упомянули.


ааа, понятно, я думаю, я не подумал о примере: string.format ("int это {0}. опять же это {0}", int);
Джим

1

Я думаю с string.Format() этим легче увидеть, каким именно будет результат (так что у вас нет проблем с забытыми пробелами или чем-то в этом роде), а также легче набирать и изменять.

Если вы хотите сделать очень простое форматирование, использование +оператора плюс может быть проще, но я склонен использовать его только при объединении двух строк, не более.

Чтобы показать, как string.Format()проще изменить, представьте, что вы хотите добавить точку в конце предложения в своем примере: переход от string.Format("The int is {0}", i)до string.Format("The int is {0}.", i)- это всего лишь один символ. Но переход от "the int is " + iк "the int is " + i + '.'намного больше.

Еще одним преимуществом string.Format()является то, что он позволяет легко указать формат для использования, например string.Format("The int is 0x{0:X}.", i). Это еще важнее при форматировании даты.

Что касается эффективности, то string.Format(), скорее всего, она медленнее простых конкатенаций строк. Но код, подобный этому, скорее всего, не на горячем пути, так что это не имеет значения. И если это произойдет, вы, вероятно, лучше использовать StringBuilder.


string.Format внутренне использует StringBuilder в любом случае
Брайан

1

Используйте тот, который делает ваш код наиболее читабельным. Не беспокойтесь о производительности.

Для вашего примера ниже я предпочитаю B, потому что это просто более читабельно. Но языковые переводы выше также имеют смысл. Не позволяйте никому заставить вас в использовании string.Format, вместо того, чтобы читать и пункт Джефф Atwoods отличным блоге на The Sad Трагедии Micro оптимизаций театра

A:

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

против

B:

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

-1

Ссылка: строка вывода: формат или конкат в C #?

Рассмотрим этот код.

Это слегка измененная версия вашего кода.

  1. Я удалил Console.WriteLine, поскольку он, вероятно, на несколько порядков медленнее, чем то, что я пытаюсь измерить.
  2. Я запускаю секундомер перед циклом и останавливаю его сразу после этого, так что я не теряю точности, если для выполнения функции требуется, например, 26,4 такта.
  3. То, как вы поделили результат на количество итераций, было неверным. Посмотрите, что произойдет, если у вас есть 1000 миллисекунд и 100 миллисекунд. В обеих ситуациях вы получите 0 мс после деления на 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);

Вот мои результаты:

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

1
Как это отвечает аспектам того, является ли первый пример кода или второй пример кода лучшим вариантом? Как учитывается итерация за полсекунды за 1M, если этот код проще поддерживать человеку или нет?

Джим спросил: «Каковы плюсы и минусы?» Это показывает, что на многих итерациях String.Format работает быстрее.
jp2code

Вы должны полностью добавить это к своему ответу, а не оставлять его как блок кода и отличия от кода ОП. В настоящее время ваш ответ не отвечает на вопрос ОП на английском языке. Посмотрите на другие ответы. Можно было бы удалить весь код из них и все же иметь ответ на вопрос ОП.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.