Оскільки я не думаю, що відповіді тут охоплюють усе, я хотів би зробити тут невелике доповнення.
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
значення, які ви 'додаєте' до рядка. На різних машинах у вас можуть виникнути різні рядки, якщо ви не використовуєте string.Format
явну CultureInfo
.
F.ex. подумайте, що станеться, якщо ви зміните "." для ',' під час написання файлу значень, розділених комами ... Голландською мовою десятковий роздільник є комою, тому ваш користувач може просто отримати 'смішний' сюрприз.
Більш детальна відповідь
Якщо ви не знаєте заздалегідь точного розміру рядка, найкраще скористатися такою політикою, щоб перерозподілити буфери, які ви використовуєте. Спочатку заповнений простір заповнюється, після чого дані копіюються.
Вирощування означає виділення нового блоку пам’яті та копіювання старих даних у новий буфер. Потім можна звільнити старий блок пам'яті. Підсумок ви отримуєте на цьому етапі: вирощування - це дорога операція.
Найпрактичніший спосіб зробити це - використовувати політику перерозподілу. Найпоширеніша політика полягає в перерозподілі буферів потужністю 2. Звичайно, ви повинні робити це трохи розумніше, ніж це (оскільки немає сенсу зростати з 1,2,4,8, якщо ви вже знаєте, що вам потрібно 128 символів ) але ви отримуєте картину. Політика гарантує, що вам не потрібно занадто багато дорогих операцій, які я описав вище.
StringBuilder
це клас, який в основному перерозподіляє основний буфер потужністю два. string.Format
використовує StringBuilder
під кришкою.
Це робить ваше рішення основним компромісом між надмірним розміщенням та додаванням (-мільти) (з / в культурою) або просто виділенням-додаванням.
string.Format
, який не використовує жодних складених функцій форматування (тобто просто простих{0}
) і замінить їх на значно більш швидке об'єднання рядків. Цікаво, що подібний подвиг досягається з існуючим переписувачем ІЛ, таким як PostSharp.