Оскільки я не думаю, що відповіді тут охоплюють усе, я хотів би зробити тут невелике доповнення.
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.