🔥 Zapisy zamknięte, ale możesz pobrać Roadmapę .NET i dołączyć do listy oczekujących — Pobierz i dołącz do Listy VIP →

StringBuilder w C# — kiedy używać i jak działa

Łańcuch string jest niezmienny — każda metoda klasy System.String tworzy nowy obiekt w pamięci (pełne omówienie w artykule Łańcuchy string w C#). Gdy modyfikujesz tekst wielokrotnie, np. w pętli, prowadzi to do tworzenia wielu zbędnych obiektów — dlaczego to realny problem wydajnościowy, tłumaczy osobny artykuł efektywne manipulowanie stringiem. Tutaj skupiamy się na samej klasie StringBuilder — rozwiązaniu tego problemu — i jej pełnym API.

Czym jest StringBuilder?

StringBuilder (z przestrzeni System.Text) to zmienny bufor znaków. Zamiast tworzyć nowy obiekt przy każdej zmianie, modyfikuje zawartość w miejscu i dynamicznie rozszerza pamięć w razie potrzeby. Gotowy tekst pobierasz metodą ToString().

Deklaracja i inicjalizacja

using System.Text;

StringBuilder sb1 = new StringBuilder();                  // pusty
StringBuilder sb2 = new StringBuilder("Witaj świecie");   // z zawartością początkową

Pojemność początkowa (nie „maksymalna”)

Liczbę całkowitą w konstruktorze często myli się z limitem. To pojemność początkowa bufora — ile znaków pomieści, zanim będzie musiał się rozszerzyć. StringBuilder rośnie automatycznie ponad tę wartość, więc nie jest to twardy limit.

StringBuilder sb = new StringBuilder(40);                 // pojemność początkowa 40
StringBuilder sb2 = new StringBuilder("Witaj świecie", 40); // zawartość + pojemność początkowa

Twardy limit można ustawić osobno — to właściwość MaxCapacity, podawana w konstruktorze new StringBuilder(capacity, maxCapacity). Ustawianie pojemności początkowej to drobna optymalizacja: gdy z góry znasz przybliżony rozmiar, ograniczasz liczbę realokacji bufora. Jeśli dowiesz się o potrzebnym rozmiarze dopiero w trakcie budowania tekstu, możesz dociągnąć pojemność później metodą EnsureCapacity(min) — gwarantuje ona, że bufor pomieści co najmniej min znaków, bez wielokrotnych, mniejszych realokacji po drodze.

Najważniejsze metody

  • Append(value) — dopisuje tekst na końcu.
  • AppendLine(value) — dopisuje tekst i znak nowej linii.
  • AppendFormat(format, args) — dopisuje sformatowany tekst.
  • Insert(index, value) — wstawia tekst na pozycji.
  • Remove(start, length) — usuwa length znaków od pozycji start.
  • Replace(oldValue, newValue) — zamienia wszystkie wystąpienia (działa na znakach i całych łańcuchach).
  • Clear() — czyści bufor.
  • ToString() — zwraca zbudowany łańcuch.

Dostęp do pojedynczego znaku — indekser

W przeciwieństwie do string, gdzie znak pod indeksem jest tylko do odczytu, indekser StringBuilder pozwala też zapisywać pojedynczy znak bez przebudowy całego bufora:

var sb = new StringBuilder("Witaj świecie");
char pierwszy = sb[0];   // 'W'
sb[0] = 'w';              // podmiana jednego znaku — O(1), bez alokacji nowego stringa
Console.WriteLine(sb);   // witaj świecie

Przykłady z wynikami

Append i AppendLine

using System;
using System.Text;

var sb = new StringBuilder("Witaj ");
sb.Append("świecie");
sb.AppendLine(" Test");        // dopisuje " Test" + nową linię
sb.Append("kolejny tekst");

Console.WriteLine(sb.ToString());
// Witaj świecie Test
// kolejny tekst

AppendFormat

var sb = new StringBuilder("Sumowana kwota to: ");
sb.AppendFormat("{0:C}", 1000);

Console.WriteLine(sb.ToString());
// Sumowana kwota to: 1 000,00 zł   (format waluty zależy od kultury)

Insert i Remove

var sb = new StringBuilder("Witaj ");
sb.Insert(6, "świecie");
Console.WriteLine(sb);   // Witaj świecie

var sb2 = new StringBuilder("Witaj świecie");
sb2.Remove(5, 8);        // usuwa " świecie" (8 znaków od indeksu 5)
Console.WriteLine(sb2);  // Witaj

Replace

var sb = new StringBuilder("Witaj świecie");
sb.Replace("świecie", "Marcin");
Console.WriteLine(sb);   // Witaj Marcin

Method chaining

Większość metod zwraca ten sam obiekt StringBuilder, więc wywołania można łączyć:

string raport = new StringBuilder()
    .AppendLine("=== Raport ===")
    .Append("Pozycji: ").Append(42).AppendLine()
    .Append("Status: OK")
    .ToString();

Pułapka: Equals() porównuje bufor, nie treść jak string

Łatwo założyć, że skoro dwa obiekty StringBuilder mają identyczną zawartość tekstową, są sobie “równe” — tak jak dwa identyczne string. To nieprawda dla domyślnego porównania referencyjnego:

var a = new StringBuilder("test");
var b = new StringBuilder("test");

Console.WriteLine(a.Equals(b));           // false — to różne obiekty (Equals sprawdza referencję i pojemność)
Console.WriteLine(a.ToString() == b.ToString()); // true — porównanie zbudowanych stringów

Jeśli chcesz porównać zawartość dwóch buforów, porównuj wyniki ToString(), a nie same obiekty StringBuilder.

Kiedy używać StringBuilder?

  • Tak: budowanie tekstu w pętli, wiele kolejnych modyfikacji, generowanie dużych ciągów (raporty, logi, eksporty — zobacz praktyczny przykład fakturowania w artykule Generowanie dokumentów i raportów).
  • Niekoniecznie: przy kilku sklejeniach czytelniejsza jest interpolacja $"..." — StringBuilder ma drobny narzut na utworzenie obiektu.
👨‍💻
Mariusz Jurczenko
Senior .NET Developer · 10+ lat doświadczenia komercyjnego

Programista .NET z doświadczeniem komercyjnym w firmach takich jak NFZ, Kamsoft, Diagnostyka, Hermes Reply Polska czy Etisoft Smart Solutions. Twórca kursów, z których skorzystało już ponad 11 000 osób w Strefie Kursów i ponad 1 000 kursantów na dev-hobby.pl.

Specjalizacja: Clean Code, Clean Architecture i uczenie programowania tak, żeby dało się je naprawdę zrozumieć — nie wykuć.

🚀 Co dalej?

Zobacz to w praktyce na wideo i pobierz darmową roadmapę, żeby ułożyć naukę w spójną ścieżkę do pierwszej pracy.

Dodaj komentarz

czytanie to początek

Zamień wiedzę w umiejętności

Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.

Pobieram roadmapę →