Как зайти в Даркнет?!
25th January, 01:11
8
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
899
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
952
0
Очень долго работает Update запрос Oracle
27th January, 09:58
916
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
907
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
942
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1727
0
период по дням
25th October, 10:44
3957
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3722
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4614
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4382
0
Помогите пожалуйста решить задачи
24th November, 23:53
6088
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4352
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4400
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Вывод строки: формат или конкат в C#?
Допустим, вы хотите вывести или объединить строки. Какой из следующих стилей вы предпочитаете?
var p = new { FirstName = "Bill", LastName = "Gates" };Console.WriteLine("{0} {1}", p.FirstName, p.LastName);Console.WriteLine(p.FirstName + " " + p.LastName);
Вы предпочитаете использовать формат или просто объединяете строки? Что у вас самое любимое? У тебя что, от одного из них болят глаза?
Есть ли у вас рациональные аргументы, чтобы использовать одно, а не другое?
Я бы предпочел второй вариант.
Я поражен, что так много людей сразу же хотят найти код, который выполняется быстрее всего. Если один миллион итераций STILL занимает меньше секунды для обработки, будет ли это каким-либо образом заметно конечному пользователю? Не очень-то похоже.
Преждевременная оптимизация = FAIL.
Я бы выбрал вариант String.Format , только потому, что он имеет наибольший смысл с архитектурной точки зрения. Я не забочусь о спектакле, Пока он не станет проблемой (а если бы это было так, я бы спросил себя: нужно ли мне объединять миллион имен сразу? Конечно, они не все поместятся на экране...)
Подумайте, если ваш клиент позже захочет изменить его, чтобы он мог настроить отображение "Firstname Lastname" или "Lastname, Firstname." с параметром форматирования,это легко - просто замените строку формата. С помощью конката вам понадобится дополнительный код. Конечно, в данном конкретном примере это не кажется большой проблемой, но экстраполируйте.
Попробуйте этот код.
Это слегка измененная версия вашего кода.
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 результат = string.Format("{0} {1}", p.FirstName, p.LastName); взято: 618мс-2213706 тиков
1000000 x результат = (p.FirstName + "" + p.LastName); взято: 166мс-595610 тиков
О боже, - прочитав один из других ответов, я попытался изменить порядок операций, - так что сначала выполните конкатенацию, а затем String.Format...
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
Таким образом, порядок операций имеет значение HUGE, или, скорее, самая первая операция является ALWAYS гораздо медленнее.
Вот результаты выполнения, в котором операции выполняются более одного раза. Я пытался изменить порядок, но обычно все идет по тем же правилам, как только первый результат игнорируется:
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 метода) постепенно ускоряются. Самым быстрым, по-видимому, является Console.WriteLine(String.Concat(...)) метод, за которым следует нормальная конкатенация, а затем отформатированные операции.
Начальная задержка запуска, скорее всего, является инициализацией консольного потока, как размещение Console.Writeline("Start!") до того, как первая операция вернет все времена в строй.
Строки неизменяемы, это означает, что один и тот же крошечный кусочек памяти используется снова и снова в вашем коде. Добавление одних и тех же двух строк вместе и создание одной и той же новой строки снова и снова не влияет на память. .Net достаточно умен, чтобы просто использовать одну и ту же ссылку на память. Поэтому ваш код на самом деле не проверяет разницу между двумя методами объединения.
Попробуйте это на размер:
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
Жалко бедных переводчиков
Если вы знаете , что ваше приложение останется на английском языке, то прекрасно, сохраните тиканье часов. Однако во многих культурах, например, в адресах обычно встречается фамилия 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");
Итак, я не знаю, чей ответ отметить в качестве ответа :)
Конкатенация строк хороша в простом сценарии, подобном этому , - это более сложно с чем-то более сложным, чем это, даже LastName, FirstName. С форматом вы можете сразу увидеть, какой будет конечная структура строки при чтении кода, с конкатенацией становится почти невозможно сразу распознать конечный результат (за исключением очень простого примера, подобного этому).
В конечном счете это означает, что, когда вы вернетесь, чтобы внести изменения в свой формат строки, у вас будет возможность либо зайти и внести несколько изменений в формат строки, либо сморщить лоб и начать перемещать все виды средств доступа к свойствам, смешанных с текстом, что с большей вероятностью приведет к проблемам.
Если вы используете .NET 3.5, вы можете использовать такой метод расширения, как этот, и получить легкий поток, с помощью такого синтаксиса манжеты:
string str = "{0} {1} is my friend. {3}, {2} is my boss.".FormatWith(prop1,prop2,prop3,prop4);
Наконец, по мере усложнения вашего приложения вы можете решить, что для разумного поддержания строк в вашем приложении вы хотите переместить их в файл ресурсов для локализации или просто в статический помощник. Это будет MUCH легче достичь, если вы постоянно использовали форматы, и ваш код может быть довольно просто переформатирован, чтобы использовать что-то вроде
string name = String.Format(ApplicationStrings.General.InformalUserNameFormat,this.FirstName,this.LastName);
Для очень простых манипуляций я бы использовал конкатенацию, но как только вы выходите за пределы 2 или 3 элементов, формат становится более подходящим IMO.
Еще одна причина предпочесть String.Format - это то, что строки .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, поэтому я также выводил тики таймера.
Вообще я предпочитаю первое, так как особенно когда строки становятся длинными, их гораздо легче читать.
Другим преимуществом является, Я считаю, одна из производительности, так как последняя фактически выполняет 2 оператора создания строк перед передачей конечной строки в метод Console.Write. String.Format использует StringBuilder под обложками, я полагаю, так что множественные конкатенации избегаются.
Однако следует отметить, что если параметры, которые вы передаете в String.Format (и другие подобные методы, такие как Console.Write), являются типами значений, то они будут упакованы перед передачей, что может обеспечить свои собственные хиты производительности. Запись в блоге об этом здесь .
Для основной конкатенации строк я обычно использую второй стиль-более легкий для чтения и более простой. Однако, если я делаю более сложную комбинацию строк, я обычно выбираю String.Format.
String.Format экономит на большом количестве цитат и плюсов...
Console.WriteLine("User {0} accessed {1} on {2}.", user.Name, fileName, timestamp);
vs
Console.WriteLine("User " + user.Name + " accessed " + fileName + " on " + timestamp + ".");
Сохранилось всего несколько хариктеров, но я думаю, что в этом примере формат делает его намного чище.
Лучшим тестом было бы наблюдать за вашей памятью с помощью Perfmon и счетчиков памяти CLR. Я понимаю, что вся причина, по которой вы хотите использовать String.Format вместо простого объединения строк, заключается в том, что, поскольку строки неизменяемы, вы излишне обременяете сборщик мусора временными строками, которые должны быть исправлены в следующем проходе.
StringBuilder и String.Format, хотя потенциально медленнее, более эффективны в памяти.
Что такого плохого в конкатенации строк?
Через неделю, 19 августа 2015 года, этому вопросу исполнится ровно семь (7) лет. Теперь есть лучший способ сделать это. Лучше с точки зрения ремонтопригодности, так как я не проводил никаких тестов производительности по сравнению с простым объединением строк (но имеет ли это значение в наши дни? разница в несколько миллисекунд?). Новый способ сделать это с C# 6.0 :
var p = new { FirstName = "Bill", LastName = "Gates" };
var fullname = $"{p.FirstName} {p.LastName}";
Эта новая функция лучше, IMO, и фактически лучше в нашем случае , поскольку у нас есть коды, в которых мы строим строки запросов, значения которых зависят от некоторых факторов. Представьте себе одну строку запроса, где у нас есть 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}";
Начиная с C# 6.0 для этого можно использовать интерполированные строки , Что еще больше упрощает формат.
var name = "Bill";
var surname = "Gates";
MessageBox.Show($"Welcome to the show, {name} {surname}!");
Интерполированное строковое выражение выглядит как строка шаблона, содержащая выражения. Интерполированное строковое выражение создает строку путем замены содержащихся в нем выражений на ToString репрезентации результатов выражений.
Интерполированные строки имеют сходную производительность с String.Format,но улучшенную читаемость и более короткий синтаксис, благодаря тому, что значения и выражения вставляются в строку.
Пожалуйста, также обратитесь к этой статье dotnetperls по интерполяции строк.
Если вы ищете способ форматирования строк по умолчанию, это имеет смысл с точки зрения читаемости и производительности (за исключением случаев, когда микросекунды будут иметь значение в вашем конкретном случае использования).
- Форматирование - это".NET " способ сделать это. Некоторые инструменты рефакторинга (Рефактор! например) даже предложит рефакторировать код в стиле конкат, чтобы использовать стиль форматирования.
- Форматирование проще оптимизировать для компилятора (хотя второй, вероятно, будет рефакторизован, чтобы использовать метод 'Concat', который является быстрым).
- Форматирование обычно понятнее для чтения (особенно с форматированием “fancy”).
- Форматирование означает неявные вызовы '.ToString' для всех переменных, что хорошо для удобства чтения.
- Согласно “эффективной C#”, реализации .NET 'WriteLine' и 'Format' перепутались, они автобокс всех типов значений (что плохо). "Эффективный C#” советует выполнять вызовы' .ToString ' явно, что IMHO является фиктивным (см. сообщение Джеффа )
- На данный момент подсказки типа форматирования не проверяются компилятором, что приводит к ошибкам во время выполнения. Однако это положение может быть изменено в будущих версиях.
Я бы использовал String.Format, но у меня также была бы строка формата в файлах ресурсов, чтобы ее можно было локализовать для других языков. Использование простой строки конкат не позволяет вам сделать это. Очевидно, что если вам никогда не нужно будет локализовать эту строку, это не повод думать об этом. Это действительно зависит от того, для чего предназначена строка.
Если он будет показан пользователю, я бы использовал String.Format, чтобы при необходимости локализовать его , а FxCop проверит орфографию для меня, на всякий случай :)
Если он содержит числа или любые другие нестроковые вещи (например, даты), я бы использовал String.Format, потому что это дает мне больше контроля над форматированием .
Если это для построения запроса типа SQL, я бы использовал Linq .
Если бы для объединения строк внутри цикла я использовал бы StringBuilder , чтобы избежать проблем с производительностью.
Если это для какого-то вывода, который пользователь не увидит, и не будет влиять на производительность, я бы использовал String.Format, потому что у меня есть привычка использовать его в любом случае, и я просто привык к нему :)
Я выбираю, основываясь на удобочитаемости. Я предпочитаю вариант форматирования, когда вокруг переменных есть некоторый текст. В этом примере:
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);
Опция форматирования позволяет мне читать имена переменных и сопоставлять их с соответствующими числами. Опция concat этого не требует. Меня все еще смущают кавычки и знаки+, но альтернатива еще хуже. Ruby?
Console.WriteLine(p.FirstName + " " + p.LastName);
С точки зрения производительности, я ожидаю, что параметр format будет медленнее, чем конкат, поскольку формат требует разбора строки . Я не помню, чтобы мне приходилось оптимизировать такого рода инструкции, но если бы я это сделал, я бы посмотрел на методы string , такие как Concat() и Join() .
Другое преимущество формата заключается в том, что строка формата может быть помещена в конфигурационный файл. Очень удобно с сообщениями об ошибках и текстом UI.
Если вы имеете дело с чем-то, что должно быть легко читаемо (и это большинство кода), я бы придерживался версии перегрузки оператора UNLESS:
- Код должен быть выполнен миллионы раз
- Вы делаете тонны конкатов (больше 4-это тонна)
- Кодекс ориентирован на создание компактной структуры
По крайней мере, при двух из этих обстоятельств я бы использовал вместо этого StringBuilder.
Очень мило!
Просто добавить
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();
И это еще быстрее (я думаю, что string.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 конката, ' + ' будет работать просто отлично для 1 конката. И если вы не заботитесь о выполнении микро-оптимизации производительности, string.Format будет работать просто отлично в общем случае.
Заметка о культуре
А еще есть нечто, называемое культурой...
string.Format позволяет использовать CultureInfo в форматировании. Простой оператор ' + ' использует текущую культуру.
Это особенно важное замечание, если вы пишете форматы файлов и f.ex. double значения, которые вы 'add' в строку. На разных машинах вы можете получить разные строки, если не используете string.Format с явным CultureInfo .
F.ex. подумайте, что произойдет, если вы измените a '.'for a ', ' во время написания вашего файла comma-seperated-values... в голландском языке десятичный разделитель-это запятая, поэтому ваш пользователь может просто получить сюрприз 'funny'.
Более детальный ответ
Если вы заранее не знаете точный размер строки, лучше всего использовать такую политику для распределения буферов, которые вы используете. Сначала заполняется провисшее пространство, после чего происходит копирование данных.
Рост означает выделение нового блока памяти и копирование старых данных в новый буфер. После этого старый блок памяти может быть освобожден. На этом этапе вы получаете главный вывод: выращивание-это дорогостоящая операция.
Наиболее практичный способ сделать это-использовать политику общего распределения. Наиболее распространенной политикой является распределение буферов в степени 2. Конечно, вы должны сделать это немного умнее (так как нет смысла расти с 1,2,4,8, если вы уже знаете, что вам нужно 128 символов), но вы получите картину. Эта политика гарантирует, что вам не нужно слишком много дорогостоящих операций, которые я описал выше.
StringBuilder -это класс, который в основном распределяет базовый буфер в степени два. string.Format использует StringBuilder под капотом.
Это делает ваше решение основным компромиссом между overallocate-and-append (- кратным) (w/w.o. культура) или просто allocate-and-append.