Поскольку я не думаю, что ответы здесь охватывают все, я хотел бы сделать небольшое дополнение здесь.
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.ex. double
значения, которые вы «добавляете» в строку. На разных машинах вы можете получить разные строки, если вы не используете string.Format
с явным CultureInfo
.
f.ex. подумайте, что произойдет, если вы измените «.» для ',' при написании файла с разделенными запятыми значениями ... на голландском языке десятичный разделитель - запятая, поэтому ваш пользователь может просто получить «забавный» сюрприз.
Более подробный ответ
Если вы заранее не знаете точный размер строки, лучше использовать такую политику, чтобы перераспределить используемые вами буферы. Сначала свободное место заполняется, после чего данные копируются.
Увеличение означает выделение нового блока памяти и копирование старых данных в новый буфер. Старый блок памяти может быть освобожден. В этом пункте вы получаете практический результат: выращивание является дорогостоящей операцией.
Наиболее практичный способ сделать это - использовать политику перераспределения. Наиболее распространенной политикой является перераспределение буферов со степенями 2. Конечно, вы должны сделать это немного умнее, чем это (так как нет смысла расти с 1,2,4,8, если вы уже знаете, что вам нужно 128 символов) ) но вы получите картину. Политика гарантирует, что вам не нужно слишком много дорогостоящих операций, которые я описал выше.
StringBuilder
- это класс, который в основном перераспределяет базовый буфер в степени два. string.Format
использует StringBuilder
под капотом.
Это делает ваше решение основным компромиссом между overallocate-and-append (-multiple) (w / w.o. Culture) или просто allocate-and-append.