Avatar ·

Лучший способ повторить символ в строке C#

Всем привет! Я новичок в C# и столкнулся с задачей, которая кажется простой, но я не уверен, как её правильно решить. Мне нужно создать строку, состоящую из повторяющегося символа. Например, я хочу получить строку из 10 символов 'X' — "XXXXXXXXXX". Или, например, для форматирования вывода сделать разделитель из 50 дефисов. Я знаю, что могу сделать это через цикл `for` или `while`, собирая строку с помощью `StringBuilder` или просто конкатенацией. Но мне кажется, что это слишком громоздко для такой простой задачи. Пример моего текущего решения: ```csharp string result = ""; for (int i = 0; i < 10; i++) { result += "X"; } ``` Но я слышал, что конкатенация строк в цикле — это плохая практика из-за производительности. Использование `StringBuilder` кажется более правильным, но всё равно требует несколько строк кода. Также я видел, что в .NET есть какие-то новые методы для работы со строками, но не уверен, какой из них лучший. Может быть, есть однострочное решение? Какой способ считается наиболее эффективным и читаемым для повторения символа в современном C#? Интересует как производительность, так и простота кода. Заранее спасибо за советы! <<>>

Использование конструктора string(char, int)

Самый простой и производительный способ в современном C# — использовать конструктор string(char c, int count). Он создаёт строку, состоящую из указанного символа, повторённого заданное количество раз. Это однострочное решение, которое работает быстро и не создаёт лишних аллокаций.

string result = new string('X', 10);
Console.WriteLine(result); // Вывод: XXXXXXXXXX

Этот метод появился ещё в ранних версиях .NET Framework и остаётся актуальным в .NET 5/6/7/8. Он использует внутреннюю оптимизацию и работает быстрее, чем ручные циклы или StringBuilder.

Альтернатива: string.Concat(Enumerable.Repeat())

Для случаев, когда символ нужно повторить, но количество заранее не известно или может быть большим, можно использовать LINQ:

string result = string.Concat(Enumerable.Repeat('X', 10));
Console.WriteLine(result); // Вывод: XXXXXXXXXX

Однако этот подход менее производителен, чем конструктор, так как создаёт промежуточную коллекцию. Используйте его только если нужно повторить не символ, а строку или объект.

Почему не цикл с конкатенацией?

Конкатенация строк через += в цикле — плохая практика, потому что строки в C# иммутабельны. Каждая операция += создаёт новую строку, копируя старую, что приводит к квадратичной сложности O(n²) по времени и памяти. Для 10 символов это незаметно, но для 100 000 — катастрофа.

// Плохо: O(n²)
string bad = "";
for (int i = 0; i < 100000; i++)
    bad += "X";

Когда использовать StringBuilder?

StringBuilder — хороший выбор, если вы повторяете не один символ, а сложную строку или комбинируете разные символы. Но для простого повторения одного символа он избыточен:

var sb = new StringBuilder(10);
for (int i = 0; i < 10; i++)
    sb.Append('X');
string result = sb.ToString();

Это работает, но требует больше кода и создаёт лишний объект StringBuilder.

Сравнение производительности (для 1 000 000 повторений)

  • Конструктор new string('X', n) — ~5 мс, 1 аллокация
  • string.Concat(Enumerable.Repeat()) — ~50 мс, много аллокаций
  • StringBuilder — ~15 мс, 2 аллокации
  • Цикл с += — ~5000 мс, 1 000 000 аллокаций (катастрофа)

Особые случаи

Если нужно повторить не один символ, а строку из нескольких символов, используйте string.Concat(Enumerable.Repeat("abc", 5)) или StringBuilder. Для очень больших строк (сотни мегабайт) рассмотрите Array.Fill с последующим созданием строки:

char[] arr = new char[1000000];
Array.Fill(arr, 'X');
string result = new string(arr);

Это даёт максимальную производительность, но требует больше кода.

Итог: Для 99% случаев используйте new string('X', count) — это самый короткий, читаемый и быстрый способ повторить символ в C#.

<<>>

Использование string.PadLeft / PadRight для повторения символа

Ещё один интересный способ, который может быть полезен в контексте форматирования — это методы PadLeft и PadRight. Они обычно используются для выравнивания строк, но их можно применить и для повторения символа:

// Повторяем символ 'X' 10 раз
string result = "".PadLeft(10, 'X');
Console.WriteLine(result); // XXXXXXXXXX

// Альтернатива через PadRight
string result2 = "".PadRight(10, 'X');
Console.WriteLine(result2); // XXXXXXXXXX

Этот подход работает, но имеет один недостаток: он создаёт пустую строку, а затем дополняет её символами. Внутренне PadLeft и PadRight также используют конструктор string(char, int), поэтому производительность практически идентична. Однако код выглядит менее очевидным для задачи "повторить символ".

Я рекомендую использовать этот метод только если вы уже работаете с выравниванием строк и хотите сохранить единообразие стиля. В остальных случаях new string('X', 10) предпочтительнее из-за ясности намерений.

Дополнительный совет: Если вам нужно повторить символ для форматирования вывода (например, разделитель), рассмотрите встроенные методы string, такие как string.Join или форматирование через интерполяцию, но для простого повторения символа — придерживайтесь конструктора.