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

предположим, что вы хотите вывести или объединить строки. Какой из следующих стилей вы предпочитаете?

  • var p = new { FirstName = "Bill", LastName = "Gates" };

  • Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

  • Console.WriteLine(p.FirstName + " " + p.LastName);

вы предпочитаете использовать формат или просто конкат строки? Какой твой любимый? У тебя что, глаза болят?

есть ли у вас какие-либо рациональные аргументы для использования одного, а не другого?

Я бы пошел на второй.

30 ответов


попробуйте этот код.

Это слегка измененная версия кода.
1. Я убрал консоль.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 х результат = строка.Формат("{0} {1}", С. Имя, С. Фамилия) приняли: 618ms - 2213706 клещей
1000000 X результат = (стр. FirstName + "" + p.Фамилия); взял: 166ms-595610 тиков


Я поражен, что так много людей сразу хотят, чтобы найти код, который выполняется быстрее. если один миллион итераций все еще занимает меньше секунды для обработки, будет ли это каким-либо образом заметно конечному пользователю? Вряд ли.

преждевременная оптимизация = провал.

Я бы пошел с String.Format вариант, только потому, что он имеет наибольший смысл с архитектурной точки зрения. Я не забочусь о производительности пока не становится проблемой (и если бы это было так, я бы спросил себя: нужно ли мне объединять миллион имен сразу? Конечно, они не все помещаются на экране...)

подумайте, если ваш клиент позже хочет изменить его, чтобы они могли настроить, следует ли отображать "Firstname Lastname" или "Lastname, Firstname." с опцией Format это легко-просто замените строку формата. С concat вам понадобится дополнительный код. Конечно, это не звучит как большое дело в этом конкретном примере, но экстраполируйте.


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

Bill Gates
Console.WriteLine(p.FirstName + " " + p.LastName); took: 8ms - 30488 ticks
Bill Gates
Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took: 0ms - 182 ticks

таким образом, порядок операций имеет огромное значение, или, скорее, самая первая операция всегда намного медленнее.

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

Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 5ms - 20335 ticks
Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 0ms - 156 ticks
Bill Gates
Console.WriteLine(FirstName + " " + LastName); took: 0ms - 122 ticks
Bill Gates
Console.WriteLine("{0} {1}", FirstName, LastName); took: 0ms - 181 ticks
Bill Gates
Console.WriteLine("{0} {1}", FirstName, LastName); took: 0ms - 122 ticks
Bill Gates
String.Concat(FirstName, " ", LastName); took: 0ms - 142 ticks
Bill Gates
String.Concat(FirstName, " ", LastName); took: 0ms - 117 ticks

Как вы можете видеть, последующие запуски одного и того же метода (я преобразовал код в 3 метода) постепенно ускоряются. Самым быстрым, по-видимому, является консоль.Метода WriteLine(Строка.Функция concat(...)) метод, за которым следует нормальная конкатенация, а затем отформатированные операции.

начальная задержка при запуске, вероятно, является инициализацией потока консоли, как размещение консоли.Writeline ("Старт!") перед первой операцией приносит все времена назад в линия.


строки неизменяемы, это означает, что один и тот же крошечный фрагмент памяти используется снова и снова в вашем коде. Добавление одних и тех же двух строк вместе и создание одной и той же новой строки снова и снова не влияет на память. .Net достаточно умен, чтобы использовать ту же ссылку на память. Поэтому ваш код действительно не проверяет разницу между двумя методами concat.

Попробуй вот это:

Stopwatch s = new Stopwatch();

int n = 1000000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0, sbElapsedMilliseconds = 0, sbElapsedTicks = 0;

Random random = new Random(DateTime.Now.Millisecond);

string result;
s.Start();
for (var i = 0; i < n; i++)
    result = (random.Next().ToString() + " " + random.Next().ToString());
s.Stop();
cElapsedMilliseconds = s.ElapsedMilliseconds;
cElapsedTicks = s.ElapsedTicks;
s.Reset();

s.Start();
for (var i = 0; i < n; i++)
    result = string.Format("{0} {1}", random.Next().ToString(), random.Next().ToString());
s.Stop();
fElapsedMilliseconds = s.ElapsedMilliseconds;
fElapsedTicks = s.ElapsedTicks;
s.Reset();

StringBuilder sb = new StringBuilder();
s.Start();
for(var i = 0; i < n; i++){
    sb.Clear();
    sb.Append(random.Next().ToString());
    sb.Append(" ");
    sb.Append(random.Next().ToString());
    result = sb.ToString();
}
s.Stop();
sbElapsedMilliseconds = s.ElapsedMilliseconds;
sbElapsedTicks = s.ElapsedTicks;
s.Reset();

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");
Console.WriteLine(n.ToString() + " x sb.Clear();sb.Append(random.Next().ToString()); sb.Append(\" \"); sb.Append(random.Next().ToString()); result = sb.ToString(); took: " + (sbElapsedMilliseconds) + "ms - " + (sbElapsedTicks) + " ticks");
Console.WriteLine("****************");
Console.WriteLine("Press Enter to Quit");
Console.ReadLine();

Пример Вывода:

1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 513ms - 1499816 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 393ms - 1150148 ticks
1000000 x sb.Clear();sb.Append(random.Next().ToString()); sb.Append(" "); sb.Append(random.Next().ToString()); result = sb.ToString(); took: 405ms - 1185816 ticks

жаль бедных переводчиков

Если вы знаю ваше приложение останется на английском языке, а затем отлично, сохраните тики часов. Однако многие культуры обычно видят Lastname Firstname, например, в адресах.

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


вот мои результаты более 100 000 итераций:

Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took (avg): 0ms - 689 ticks
Console.WriteLine(p.FirstName + " " + p.LastName); took (avg): 0ms - 683 ticks

и вот код стенда:

Stopwatch s = new Stopwatch();

var p = new { FirstName = "Bill", LastName = "Gates" };

//First print to remove the initial cost
Console.WriteLine(p.FirstName + " " + p.LastName);
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

int n = 100000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;

for (var i = 0; i < n; i++)
{
    s.Start();
    Console.WriteLine(p.FirstName + " " + p.LastName);
    s.Stop();
    cElapsedMilliseconds += s.ElapsedMilliseconds;
    cElapsedTicks += s.ElapsedTicks;
    s.Reset();
    s.Start();
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
    s.Stop();
    fElapsedMilliseconds += s.ElapsedMilliseconds;
    fElapsedTicks += s.ElapsedTicks;
    s.Reset();
}

Console.Clear();

Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took (avg): " + (fElapsedMilliseconds / n) + "ms - " + (fElapsedTicks / n) + " ticks");
Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took (avg): " + (cElapsedMilliseconds / n) + "ms - " + (cElapsedTicks / n) + " ticks");

Итак, я не знаю, чей ответ отметить как ответ:)


Конкатенирование строк прекрасно в таком простом сценарии - это сложнее с чем-то более сложным, чем это, даже фамилия, имя. С форматом вы можете сразу увидеть, какой будет конечная структура строки при чтении кода, с конкатенацией становится практически невозможно сразу распознать конечный результат (за исключением очень простого примера, подобного этому).

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

Если вы используете .NET 3.5, вы можете использовать метод расширения как это и получить легкий поток, от синтаксиса манжеты, как это:

string str = "{0} {1} is my friend. {3}, {2} is my boss.".FormatWith(prop1,prop2,prop3,prop4);

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

string name = String.Format(ApplicationStrings.General.InformalUserNameFormat,this.FirstName,this.LastName);

для очень простой манипуляции я бы использовал конкатенацию, но как только вы выходите за рамки 2 или 3 элементов, формат становится более подходящим IMO.

еще одна причина предпочесть String.Формат заключается в том, что строки .NET неизменяемы и при этом создается меньше временных/промежуточных копий.


использовать следующий код:

    System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();

    var p = new { FirstName = "Bill", LastName = "Gates" };

    s.Start();
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
    s.Stop();
    Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took: " + s.ElapsedMilliseconds + "ms - " + s.ElapsedTicks + " ticks");

    s.Reset();
    s.Start();
    Console.WriteLine(p.FirstName + " " + p.LastName);
    s.Stop();

    Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took: " + s.ElapsedMilliseconds + "ms - " + s.ElapsedTicks + " ticks");

Я получил следующие результаты:

Bill Gates
Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took: 2ms - 7280 ticks
Bill Gates
Console.WriteLine(p.FirstName + " " + p.LastName); took: 0ms - 67 ticks

использование метода форматирования более 100 раз медленнее!! Конкатенация даже не регистрировалась как 1ms,поэтому я также выводил таймер.


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

строку.Формат экономит на множестве кавычек и плюсов...

Console.WriteLine("User {0} accessed {1} on {2}.", user.Name, fileName, timestamp);
vs
Console.WriteLine("User " + user.Name + " accessed " + fileName + " on " + timestamp + ".");

всего несколько charicters спас, но я думаю, в этом примере формат делает его намного чище.


лучшим тестом было бы наблюдать за вашей памятью с помощью Perfmon и счетчиков памяти CLR. Я понимаю, что вся причина, по которой вы хотите использовать String.Формат вместо того, чтобы просто объединять строки, поскольку строки неизменяемы, вы излишне обременяете сборщик мусора временными строками, которые необходимо восстановить в следующем проходе.

StringBuilder и String.Форматирование, хотя и потенциально медленнее, более эффективно для памяти.

что так плохо о конкатенации строк?


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

другое преимущество-я считаю, что один из производительности, так как последний фактически выполняет 2 оператора создания строки перед передачей последней строки в консоль.Метод write. Строка.Формат использует StringBuilder под обложками, которые я считаю, поэтому избегаются множественные конкатенации.

следует отметить, однако, что если параметры, которые вы передаете в Строка.Format (и другие такие методы, как Console.Write) - это типы значений, которые будут упакованы перед передачей, что может обеспечить собственные хиты производительности. сообщение в блоге об этом здесь.


начиная с C# 6.0 интерполируемой строки можно использовать для этого,что еще больше упрощает формат.

var name = "Bill";
var surname = "Gates";
MessageBox.Show($"Welcome to the show, {name} {surname}!");

интерполированное строковое выражение выглядит как строка шаблона, содержащая выражения. Интерполированное выражение типа String создает строку путем замены содержащихся в нем выражений с toString результатов выражений.

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

Смотрите также эта статья dotnetperls при интерполяции строк.

Если вы ищете способ форматирования строк по умолчанию, это имеет смысл с точки зрения читаемости и производительности (за исключением случаев, когда микросекунды будут иметь значение в вашем конкретном случае использования).


  1. форматирование-это" .NET " способ сделать это. Некоторые инструменты рефакторинга (Refactor! для одной) даже предлагаю рефакторинг метода concat-стиле код, чтобы использовать стиль форматирования.
  2. форматирование проще оптимизировать для компилятора (хотя второй, вероятно, будет рефакторирован для использования быстрого метода "Concat").
  3. форматирование обычно понятнее для чтения (особенно с "причудливым" форматированием).
  4. форматирование означает неявные вызовы '.ToString ' на всех переменных, что хорошо для удобочитаемости.
  5. в соответствии с" эффективным C# "реализации .NET" WriteLine " и "Format" перепутались, они autobox все типы значений (что плохо). "Эффективный C#" советует выполнить ".Вызовы ToString явно, что IMHO является фиктивным (см. Джефф)
  6. на данный момент подсказки типа форматирования не проверяются компилятором, что приводит к ошибкам во время выполнения. Однако в будущем это может быть изменено. версии.

Я выбираю на основе читаемости. Я предпочитаю вариант формата, когда вокруг переменных есть текст. В этом примере:

Console.WriteLine("User {0} accessed {1} on {2}.", 
                   user.Name, fileName, timestamp);

вы понимаете значение даже без переменных имен, тогда как конкат загроможден кавычками и знаками + и смущает мои глаза:

Console.WriteLine("User " + user.Name + " accessed " + fileName + 
                  " on " + timestamp + ".");

(Я взял пример Майка, потому что мне это нравится)

если строка формата не означает много без имен переменных, я должен использовать concat:

   Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

в опция format заставляет меня читать имена переменных и сопоставлять их с соответствующими номерами. Опция concat не требует этого. Я все еще смущен кавычками и знаками+, но альтернатива хуже. Руби?

   Console.WriteLine(p.FirstName + " " + p.LastName);

производительность мудрая, я ожидаю, что опция формата будет медленнее, чем concat, так как формат требует, чтобы строка была парсится. Я не помню, чтобы нужно было оптимизировать такую инструкцию, но если бы я это сделал, я бы посмотрел на string методы Concat() и Join().

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


Если вы намерены локализовать результат, то String.Формат имеет важное значение, потому что различные естественные языки могут даже не иметь данные в том же порядке.


Я бы использовал строку.Формат, но у меня также будет строка формата в файлах ресурсов, чтобы ее можно было локализовать для других языков. Использование простой строки concat не позволяет вам это сделать. Очевидно, что если вам никогда не понадобится локализовать эту строку,это не повод думать. Это действительно зависит от того, для чего предназначена строка.

Если он будет показан пользователю, я бы использовал String.Формат, чтобы я мог локализовать, если мне нужно - и FxCop будет проверить его для меня, на всякий случай :)

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

Если это для создания запроса, такого как SQL, я бы использовал в LINQ.

Если для объединения строк внутри цикла я бы использовал StringBuilder чтобы избежать проблем с производительностью.

Если это для некоторого вывода, пользователь не увидит и не собирается производительность эффекта я бы использовал String.Формат, потому что я привык использовать его в любом случае, и я просто привык к нему:)


через неделю 19 августа 2015 года этому вопросу будет ровно семь (7) лет. Теперь есть лучший способ сделать это. лучше в плане ремонтопригодности, так как я не делал никаких тестов производительности по сравнению с просто конкатенации строк (но разве это важно в эти дни? разница в несколько миллисекунд?). Новый способ сделать это с C# 6.0:

var p = new { FirstName = "Bill", LastName = "Gates" };
var fullname = $"{p.FirstName} {p.LastName}";

эта новая функция лучше ИМО, и на самом деле лучше в нашем дело поскольку у нас есть коды, где мы строим строки запросов, значения которых зависят от некоторых факторов. Представьте себе одну строку запроса, где у нас есть 6 аргументов. Поэтому вместо того, чтобы делать, например:

var qs = string.Format("q1={0}&q2={1}&q3={2}&q4={3}&q5={4}&q6={5}", 
    someVar, anotherVarWithLongName, var3, var4, var5, var6)

В может быть написано так, и это легче читать:

var qs=$"q1={someVar}&q2={anotherVarWithLongName}&q3={var3}&q4={var4}&q5={var5}&q6={var6}";

Если вы имеете дело с чем-то, что должно быть легко читаемым (и это самый код), я бы придерживался версии перегрузки оператора, если:

  • код должен быть казнены миллионы раз!--4-->
  • Вы делаете тонн concats (более 4 т)
  • код ориентирован на Compact Framework

по крайней мере в двух из этих обстоятельств я бы использовал StringBuilder вместо этого.


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

Выберите правильный инструмент на основе задания: D в зависимости от того, что выглядит чистым!


Я предпочитаю второй, но у меня нет рациональных аргументов в настоящее время, чтобы поддержать эту позицию.


молодец!

просто добавил

        s.Start();
        for (var i = 0; i < n; i++)
            result = string.Concat(p.FirstName, " ", p.LastName);
        s.Stop();
        ceElapsedMilliseconds = s.ElapsedMilliseconds;
        ceElapsedTicks = s.ElapsedTicks;
        s.Reset();

и это еще быстрее (я думаю, строка.Concat вызывается в обоих примерах, но первый требует какого-то перевода).

1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 249ms - 3571621 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 65ms - 944948 ticks
1000000 x result = string.Concat(p.FirstName, " ", p.LastName); took: 54ms - 780524 ticks

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

Console.WriteLine(string format, params object[] pars) звонки string.Format. "+"Подразумевает конкатенацию строк. Я не думаю, что это всегда связано со стилем; я склонен смешивать два стиля в зависимости от контекста, в котором я нахожусь.

короткий ответ:

решение вы столкнулись связано с выделением строки. Я постараюсь все упростить.

говорите вы есть

string s = a + "foo" + b;

если вы выполните это, то будут оценивать следующим образом:

string tmp1 = a;
string tmp2 = "foo" 
string tmp3 = concat(tmp1, tmp2);
string tmp4 = b;
string s = concat(tmp3, tmp4);

tmp на самом деле это не локальная переменная, но она является временной для JIT (она нажата в стеке IL). Если вы нажмете строку в стеке (например,ldstr в IL для литералов), вы помещаете ссылку на строковый указатель в стек.

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

что меняет вопрос на: Как вы можете уменьшить количество concat операции?

Итак, грубый ответ:string.Format для > 1 concats, ' + ' будет работать просто отлично для 1 concat. И если вы не заботитесь о микро-оптимизация производительности, string.Format будет работать нормально в общем случае.

заметка о культуре

и тогда есть что-то, называемое культурой...

string.Format позволяет использовать CultureInfo в форматирование. Простой оператор ' + ' использует текущую культуру.

это особенно важное замечание, если вы пишете форматы файлов и f.бывший. double значения, которые вы "добавляете" в строку. На разных машинах вы можете получить разные строки, если не используете string.Format с явным CultureInfo.

F. ex. рассмотрим, что произойдет, если вы измените '."для", " При написании файла с разделенными запятыми значениями... на голландском языке десятичный разделитель-запятая, поэтому ваш пользователь может просто получить "забавный" сюрприз.

более подробный ответ!--24-->

если вы заранее не знаете точный размер строки, лучше всего использовать такую политику для перераспределения используемых буферов. Сначала заполняется пространство slack, после чего данные копируются.

растет означает выделение нового блока памяти и копирование старых данных в новый буфер. Старый блок памяти может быть освобожден. На этом этапе вы получаете нижнюю строку: выращивание-дорогостоящая операция.

самый практичный способ сделать это-использовать политику перераспределения. Наиболее распространенным политики является overallocate буферов в 2 раза. Конечно, вы должны сделать это немного умнее (так как это не имеет смысла вырастить из 1,2,4,8 если вы уже знаете, что нужно 128 символов), но вы получите картину. Политика гарантирует, что вам не нужно слишком много дорогостоящих операций, которые я описал выше.

StringBuilder - это класс, который в основном overallocates буфера в полномочия два. string.Format использует StringBuilder под капотом.

это делает ваше решение основным компромиссом между overallocate-and-append (- multiple) (w/w).o. культура) или просто выделить и добавить.


лично, второй, поскольку все, что вы используете, находится в прямом порядке, он будет выведен. В то время как с первым вы должны сопоставить {0} и {1} с правильным var, который легко испортить.

по крайней мере, это не так плохо, как C++ sprintf, где, если вы получите тип переменной неправильно, все это взорвется.

кроме того, поскольку второй является встроенным, и ему не нужно выполнять поиск и замену всех {0} вещей, последний должно быть быстрее... хотя я точно не знаю.


Мне действительно нравится первый, потому что, когда есть много переменных, смешанных с текстом, мне кажется, легче читать. Кроме того, при использовании строки легче иметь дело с кавычками.Формат (), формат. Вот достойный анализ в конкатенации строк.


Я всегда шел по струне.Format () route. Возможность хранить форматы в переменных, таких как пример Натана, является большим преимуществом. В некоторых случаях я могу добавить переменную, но один раз больше, чем 1 переменная объединяется I рефакторинг для использования форматирования.


О, и просто для полноты, следующее несколько тиков быстрее, чем нормальная конкатенация:

Console.WriteLine(String.Concat(p.FirstName," ",p.LastName));

первый (формат) выглядит лучше меня. Это более читабельно, и вы не создаете дополнительные временные строковые объекты.


мне было любопытно, где StringBuilder стоял с этими тестами. Результаты ниже...

class Program {
   static void Main(string[] args) {

      var p = new { FirstName = "Bill", LastName = "Gates" };

      var tests = new[] {
         new { Name = "Concat", Action = new Action(delegate() { string x = p.FirstName + " " + p.LastName; }) },
         new { Name = "Format", Action = new Action(delegate() { string x = string.Format("{0} {1}", p.FirstName, p.LastName); }) },
         new { Name = "StringBuilder", Action = new Action(delegate() {
            StringBuilder sb = new StringBuilder();
            sb.Append(p.FirstName);
            sb.Append(" ");
            sb.Append(p.LastName);
            string x = sb.ToString();
         }) }
      };

      var Watch = new Stopwatch();
      foreach (var t in tests) {
         for (int i = 0; i < 5; i++) {
            Watch.Reset();
            long Elapsed = ElapsedTicks(t.Action, Watch, 10000);
            Console.WriteLine(string.Format("{0}: {1} ticks", t.Name, Elapsed.ToString()));
         }
      }
   }

   public static long ElapsedTicks(Action ActionDelg, Stopwatch Watch, int Iterations) {
      Watch.Start();
      for (int i = 0; i < Iterations; i++) {
         ActionDelg();
      }
      Watch.Stop();
      return Watch.ElapsedTicks / Iterations;
   }
}

результаты:

Concat: 406 ticks
Concat: 356 ticks
Concat: 411 ticks
Concat: 299 ticks
Concat: 266 ticks
Format: 5269 ticks
Format: 954 ticks
Format: 1004 ticks
Format: 984 ticks
Format: 974 ticks
StringBuilder: 629 ticks
StringBuilder: 484 ticks
StringBuilder: 482 ticks
StringBuilder: 508 ticks
StringBuilder: 504 ticks

согласно материалам MCSD prep, Microsoft предлагает использовать оператор + при работе с очень небольшим количеством конкатенаций (возможно, от 2 до 4). Я все еще не уверен, почему, но это то, что нужно учитывать.