String vs. StringBuilder


215

Rozumiem różnicę między Stringi StringBuilder(StringBuilder jest zmienny), ale czy istnieje duża różnica w wydajności między nimi?

Program, nad którym pracuję, ma wiele dołączonych ciągów znaków (ponad 500). Czy korzystasz StringBuilderz lepszego wyboru?

Odpowiedzi:


236

Tak, różnica w wydajności jest znacząca. Zobacz artykuł z bazy wiedzy „ Jak poprawić wydajność konkatenacji ciągów w Visual C # ”.

Zawsze starałem się najpierw napisać kod dla zachowania przejrzystości, a następnie zoptymalizować go pod kątem wydajności. To o wiele łatwiejsze niż robienie tego na odwrót! Jednak widząc ogromną różnicę wydajności w moich aplikacjach między tymi dwoma, teraz myślę o tym nieco ostrożniej.

Na szczęście stosunkowo łatwo jest przeprowadzić analizę wydajności kodu, aby zobaczyć, gdzie spędzasz czas, a następnie zmodyfikować go, aby używał w StringBuilderrazie potrzeby.


44
Dobrą zasadą jest używanie ciągów, gdy nie zamierzasz go zmieniać, i używanie StringBuilder, jeśli będziesz go zmieniać.
Tim

31
Bardzo podoba mi się ta odpowiedź, zwłaszcza porady dotyczące kodowania dla zachowania przejrzystości przed wykonaniem. Jako programiści poświęcamy tyle samo czasu na czytanie kodu, co jego pisanie.
Scott Lawrence

Outlaw: Myślę, że powinna stać się własną odpowiedzią, nad którą głosuje się osobno, jeśli dobrze rozumiem StackOverflow.
Jay Bazuzi,

2
na podstawie mojego doświadczenia, jeśli próbujesz łączyć około 10-15 sznurka, możesz iść ze sznurkiem, ale jeśli nie. ciągów jest czymś więcej niż użyj konstruktora ciągów
Peeyush

3
To wciąż zależy od tego, jak się go używa, jako odniesienie do faktycznie testujących lubię Coding Horror - The Sad Tragedy of Micro-Optimization Theatre
Erik Philips

56

Aby wyjaśnić, co Gillian powiedziała o 4 łańcuchach, jeśli masz coś takiego:

string a,b,c,d;
 a = b + c + d;

wtedy byłoby szybciej przy użyciu ciągów i operatora plusa. Wynika to z faktu, że (podobnie jak Java, jak wskazuje Eric), wewnętrznie używa StringBuilder automatycznie (w rzeczywistości używa prymitywów, których używa StringBuilder)

Jeśli jednak to, co robisz, jest bliższe:

string a,b,c,d;
 a = a + b;
 a = a + c;
 a = a + d;

Następnie musisz jawnie użyć StringBuilder. .Net nie tworzy tutaj automatycznie StringBuilder, ponieważ byłoby to bezcelowe. Na końcu każdej linii „a” musi być (niezmiennym) łańcuchem, więc musiałby utworzyć i umieścić StringBuilder w każdej linii. Aby uzyskać szybkość, musisz używać tego samego StringBuilder, dopóki nie skończysz budować:

string a,b,c,d;
StringBuilder e = new StringBuilder();
 e.Append(b);
 e.Append(c);
 e.Append(d);
 a = e.ToString();

5
Nie ma powodu, dla którego kompilator C # musi traktować drugą próbkę inaczej niż pierwsza. W szczególności nie ma obowiązku tworzenia łańcucha na końcu każdej linii. Kompilator może zachowywać się tak, jak mówisz, ale nie ma takiego obowiązku.
CodesInChaos

@CodesInChaos, niezmienna zmienna łańcuchowa jest przypisywana konkretnie na końcu każdej linii, czy to nie stwarza obowiązku wytworzenia łańcucha? Zgadzam się jednak z twierdzeniem, że nie ma powodu, aby traktować każdą linię indywidualnie inaczej (i nie jestem pewien, czy tak się dzieje), jednak utrata wydajności wynika z realokacji, więc nie ma znaczenia.
Saeb Amini

@ SaebAmini - Jeśli ajest zmienną lokalną, a obiekt, do którego się odwołuje, nie został przypisany do żadnej innej zmiennej (która może być dostępna dla innego wątku), dobry optymalizator może stwierdzić, że żaden inny koda nie uzyskuje dostępu podczas tej sekwencji linie; tylko końcowa wartość spraw. Mogłoby to potraktować te trzy wiersze kodu tak, jakby były napisane . aa = b + c + d;
ToolmakerSteve,

29

StringBuilder jest preferowany, JEŚLI robisz wiele pętli lub widelców w swoim kodzie przepustowym ... jednak dla wydajności PURE, jeśli możesz uniknąć SINGLE deklaracji ciągu, to jest to o wiele bardziej wydajne.

Na przykład:

string myString = "Some stuff" + var1 + " more stuff"
                  + var2 + " other stuff" .... etc... etc...;

jest bardziej wydajny niż

StringBuilder sb = new StringBuilder();
sb.Append("Some Stuff");
sb.Append(var1);
sb.Append(" more stuff");
sb.Append(var2);
sb.Append("other stuff");
// etc.. etc.. etc..

W takim przypadku StringBuild można uznać za łatwiejsze w utrzymaniu, ale nie jest ono bardziej wydajne niż deklaracja pojedynczego ciągu.

9 razy na 10 ... użyj konstruktora ciągów.

Na marginesie: string + var jest również bardziej wydajny niż string.Formatowanie (ogólnie), które korzysta z StringBuilder wewnętrznie (w razie wątpliwości ... sprawdź reflektor!)


17
Chciałbym, żebyś powiedział, skąd to wiesz / jak to zweryfikować.
ChrisW,

2
Nie weryfikujesz wydajności w odbłyśniku: weryfikujesz wydajność poprzez kod czasowy wydania, analizujesz za pomocą profilera i szukasz wyjaśnienia w odbłyśniku.
Albin Sunnanbo

3
Rozważ użycie String.Format () do połączenia niewielkiej liczby małych ciągów, szczególnie w przypadku formatowania wiadomości w celu pokazania użytkownikowi.
Gary Kindel,

1
To bardzo zła informacja. („string myString jest bardziej wydajny”) w ogóle nie jest prawdą.
Tom Stickel,

3
Informacje w tej odpowiedzi są niepoprawne. StringBuilder jest trochę szybszy niż konkatenacja wykonywana w tej samej instrukcji; Jednak zauważysz różnicę między nimi, jeśli zrobisz to setki tysięcy razy ( Źródło ). Jak powiedziano w źródle, „to po prostu nie ma znaczenia!”
David Sherret

25

Prosty przykład pokazujący różnicę prędkości przy stosowaniu Stringkonkatenacji vs StringBuilder:

System.Diagnostics.Stopwatch time = new Stopwatch();
string test = string.Empty;
time.Start();
for (int i = 0; i < 100000; i++)
{
    test += i;
}
time.Stop();
System.Console.WriteLine("Using String concatenation: " + time.ElapsedMilliseconds + " milliseconds");

Wynik:

Za pomocą konkatenacji ciągów: 15423 milisekundy

StringBuilder test1 = new StringBuilder();
time.Reset();
time.Start();
for (int i = 0; i < 100000; i++)
{
    test1.Append(i);
}
time.Stop();
System.Console.WriteLine("Using StringBuilder: " + time.ElapsedMilliseconds + " milliseconds");

Wynik:

Za pomocą StringBuilder: 10 milisekund

W rezultacie pierwsza iteracja zajęła 15423 ms, a druga iteracja StringBuilder zajęła 10 ms.

Wydaje mi się, że używanie StringBuilderjest szybsze, dużo szybsze.


24

Ten test porównawczy pokazuje, że regularne łączenie jest szybsze przy łączeniu 3 lub mniejszej liczby łańcuchów.

http://www.chinhdo.com/20070224/stringbuilder-is-not-always-faster/

StringBuilder może znacznie poprawić wykorzystanie pamięci, szczególnie w przypadku dodania 500 łańcuchów razem.

Rozważ następujący przykład:

string buffer = "The numbers are: ";
for( int i = 0; i < 5; i++)
{
    buffer += i.ToString();
}
return buffer;

Co dzieje się w pamięci? Tworzone są następujące ciągi znaków:

1 - "The numbers are: "
2 - "0"
3 - "The numbers are: 0"
4 - "1"
5 - "The numbers are: 01"
6 - "2"
7 - "The numbers are: 012"
8 - "3"
9 - "The numbers are: 0123"
10 - "4"
11 - "The numbers are: 01234"
12 - "5"
13 - "The numbers are: 012345"

Dodając te pięć liczb na końcu łańcucha, stworzyliśmy 13 obiektów łańcuchowych! I 12 z nich było bezużytecznych! Łał!

StringBuilder rozwiązuje ten problem. Nie jest to „zmienny ciąg”, jak często słyszymy ( wszystkie ciągi w .NET są niezmienne ). Działa poprzez utrzymanie wewnętrznego bufora, tablicy znaków. Wywołanie Append () lub AppendLine () dodaje ciąg do pustego miejsca na końcu tablicy char; jeśli tablica jest zbyt mała, tworzy nową, większą tablicę i kopiuje tam bufor. Tak więc w powyższym przykładzie StringBuilder może potrzebować tylko jednej tablicy do przechowywania wszystkich 5 dodatków do łańcucha - w zależności od wielkości bufora. Możesz powiedzieć StringBuilder, jak duży powinien być jego bufor w konstruktorze.


2
Drobna nit: trochę dziwnie jest powiedzieć „stworzyliśmy 13 obiektów łańcuchowych, a 12 z nich było bezużytecznych”, a następnie powiedzieć, że StringBuilder rozwiązuje ten problem. W końcu sześć ciągów, które nie masz innego wyboru, jak stworzyć; oni są z i.ToString(). Zatem w StringBuilder nadal musisz tworzyć ciągi 6 + 1; zredukował tworzenie 13 łańcuchów do utworzenia 7 łańcuchów. Ale to wciąż niewłaściwy sposób patrzenia na to; utworzenie ciągów sześciu liczb nie jest istotne. Konkluzja: po prostu nie powinieneś wspominać o sześciu ciągach utworzonych przez i.ToString(); nie są one częścią porównania wydajności.
ToolmakerSteve,

12

Tak, StringBuilderdaje lepszą wydajność podczas powtarzania operacji na łańcuchu. Dzieje się tak, ponieważ wszystkie zmiany są wprowadzane w jednym wystąpieniu, dzięki czemu można zaoszczędzić dużo czasu zamiast tworzyć nowe, takie jak wystąpienie String.

String Vs Stringbuilder

  • String

    1. w Systemprzestrzeni nazw
    2. niezmienna (tylko do odczytu) instancja
    3. wydajność spada, gdy zachodzi ciągła zmiana wartości
    4. wątek bezpieczny
  • StringBuilder (zmienny ciąg)

    1. pod System.Textprzestrzeni nazw
    2. zmienna instancja
    3. wykazuje lepszą wydajność, ponieważ wprowadzono nowe zmiany do istniejącej instancji

Zdecydowanie polecam artykuł dotnet mob: String Vs StringBuilder w C # .

Powiązane pytanie przepełnienia stosu: Zmienność ciągu, gdy ciąg nie zmienia się w C #? .


12

String Vs String Builder:

Po pierwsze musisz wiedzieć, w którym zgromadzeniu żyją te dwie klasy?

Więc,

ciąg jest obecny w Systemprzestrzeni nazw.

i

StringBuilder jest obecny w System.Textprzestrzeni nazw.

Do deklaracji ciągu :

Musisz dołączyć Systemprzestrzeń nazw. coś takiego. Using System;

i

Dla StringBuilder deklaracji :

Musisz dołączyć System.textprzestrzeń nazw. coś takiego. Using System.text;

Teraz przyjdź aktualne pytanie.

Jaki jest differene pomiędzy ciągiem & StringBuilder ?

Główną różnicą między tymi dwoma jest to, że:

strunowy jest niezmienny.

i

StringBuilder można modyfikować.

Teraz omówmy różnicę między niezmienną a zmienną

Zmienny: oznacza zmienny .

Niezmienny: oznacza, że ​​nie można go zmienić.

Na przykład:

using System;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // String Example

            string name = "Rehan";
            name = name + "Shah";
            name = name + "RS";
            name = name + "---";
            name = name + "I love to write programs.";

            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah RS --- I love to write programs."
        }
    }
}

W tym przypadku zamierzamy zmienić ten sam obiekt 5 razy.

Więc oczywiste pytanie jest takie! Co tak naprawdę dzieje się pod maską, kiedy zmieniamy ten sam ciąg 5 razy.

Tak się dzieje, gdy zmieniamy ten sam ciąg 5 razy.

spójrzmy na postać.

wprowadź opis zdjęcia tutaj

Wyjaśnienie:

Kiedy po raz pierwszy inicjujemy tę zmienną „name” na „Rehan” tj string name = "Rehan" Ta zmienna jest tworzona na stosie „name” i wskazuje na tę wartość „Rehan”. po wykonaniu tej linii: „name = name +„ Shah ”. zmienna referencyjna nie wskazuje już na ten obiekt„ Rehan ”, teraz wskazuje na„ Shah ”i tak dalej.

stringJest zatem niezmienne, że po utworzeniu obiektu w pamięci nie możemy go zmienić.

Tak więc, kiedy konatynizujemy namezmienną, poprzedni obiekt pozostaje tam w pamięci i tworzony jest kolejny nowy obiekt łańcuchowy ...

Tak więc z powyższej figury mamy pięć obiektów, cztery obiekty są wyrzucane, w ogóle nie są używane. Wciąż pozostają w pamięci i wykorzystują ilość pamięci. „Garbage Collector” jest odpowiedzialny za to, aby oczyścić zasoby z pamięci.

Tak więc w przypadku łańcucha znaków w dowolnym momencie, gdy manipulujemy nim w kółko, mamy kilka obiektów utworzonych i pozostają tam w pamięci.

Oto historia zmiennego łańcucha.

Teraz spójrzmy na obiekt StringBuilder. Na przykład:

using System;
using System.Text;

namespace StringVsStrigBuilder
{
    class Program
    {
        static void Main(string[] args)
        {
            // StringBuilder Example

            StringBuilder name = new StringBuilder();
            name.Append("Rehan");
            name.Append("Shah");
            name.Append("RS");
            name.Append("---");
            name.Append("I love to write programs.");


            // Now when I run this program this output will be look like this.
            // output : "Rehan Shah Rs --- I love to write programs."
        }
    }
}

W tym przypadku zamierzamy zmienić ten sam obiekt 5 razy.

Więc oczywiste pytanie jest takie! Co tak naprawdę dzieje się pod maską, kiedy zmieniamy ten sam StringBuilder 5 razy.

Tak się dzieje, gdy zmieniamy ten sam StringBuilder 5 razy.

spójrzmy na postać. wprowadź opis zdjęcia tutaj

Wyjaśnienie: W przypadku obiektu StringBuilder. nie dostaniesz nowego obiektu. Ten sam obiekt zostanie zmieniony w pamięci, więc nawet jeśli zmienisz obiekt i powiedzmy 10 000 razy, nadal będziemy mieć tylko jeden obiekt stringBuilder.

Nie masz dużo obiektów śmieciowych ani niereferencjonowanych obiektów stringBuilder, ponieważ można to zmienić. Jest zmienny, co oznacza, że ​​zmienia się z czasem?

Różnice:

  • Łańcuch występuje w przestrzeni nazw System, gdzie jako Stringbuilder występuje w przestrzeni nazw System.Text.
  • ciąg jest niezmienny, gdy StringBuilder jest mutabe.

8

StringBuilder zmniejsza liczbę przydziałów i przypisań kosztem dodatkowej pamięci używanej. Właściwie użyte, może całkowicie wyeliminować potrzebę kompilacji do przydzielania coraz większych ciągów znaków, aż do znalezienia wyniku.

string result = "";
for(int i = 0; i != N; ++i)
{
   result = result + i.ToString();   // allocates a new string, then assigns it to result, which gets repeated N times
}

vs.

String result;
StringBuilder sb = new StringBuilder(10000);   // create a buffer of 10k
for(int i = 0; i != N; ++i)
{
   sb.Append(i.ToString());          // fill the buffer, resizing if it overflows the buffer
}

result = sb.ToString();   // assigns once

5

Wydajność operacji konkatenacji dla obiektu String lub StringBuilder zależy od częstotliwości alokacji pamięci. Operacja konkatenacji String zawsze przydziela pamięć, natomiast operacja konkatenacji StringBuilder przydziela pamięć tylko wtedy, gdy bufor obiektu StringBuilder jest zbyt mały, aby pomieścić nowe dane. W związku z tym klasa String jest preferowana w przypadku operacji konkatenacji, jeśli połączona jest stała liczba obiektów String. W takim przypadku poszczególne operacje konkatenacji mogą nawet zostać połączone przez kompilatora w jedną operację. Obiekt StringBuilder jest preferowany dla operacji konkatenacji, jeśli dowolna liczba łańcuchów jest konkatenowana; na przykład, jeśli pętla łączy losową liczbę ciągów danych wejściowych użytkownika.

Źródło: MSDN


3

StringBuilder jest lepszy do budowania łańcucha z wielu niestałych wartości.

Jeśli budujesz ciąg z wielu stałych wartości, takich jak wiele wierszy wartości w dokumencie HTML lub XML lub innych fragmentach tekstu, możesz uniknąć dodawania do tego samego ciągu, ponieważ prawie wszystkie kompilatory „stałe składanie”, proces zmniejszania parsowania drzewa, gdy masz kilka ciągłych manipulacji (jest również używany, gdy piszesz coś takiego int minutesPerYear = 24 * 365 * 60). A w prostych przypadkach z dołączonymi do siebie niestałymi wartościami kompilator .NET zredukuje kod do czegoś podobnego do tego, co StringBuilderrobi.

Ale gdy kompilator nie może zredukować Twojego dodatku do czegoś prostszego, będziesz chciał StringBuilder. Jak wskazuje fizch, jest to bardziej prawdopodobne w pętli.


2

Wierzę, że StringBuilder jest szybszy, jeśli masz więcej niż 4 ciągi, które musisz dołączyć razem. Plus może robić fajne rzeczy, takie jak AppendLine.


2

W .NET StringBuilder jest nadal szybszy niż dodawanie ciągów. Jestem prawie pewien, że w Javie po prostu dodają StringBuffer pod maską, gdy dodasz ciągi, więc tak naprawdę nie ma różnicy. Nie jestem pewien, dlaczego jeszcze tego nie zrobili w .NET.



2

Używanie ciągów do konkatenacji może prowadzić do złożoności środowiska wykonawczego w kolejności od O(n^2).

Jeśli używasz a StringBuilder, musisz wykonać o wiele mniej kopiowania pamięci. Dzięki StringBuilder(int capacity)możesz zwiększyć wydajność, jeśli potrafisz oszacować, jak duży będzie finał String. Nawet jeśli nie jesteś precyzyjny, prawdopodobnie będziesz musiał zwiększyć pojemność StringBuildertylko kilka razy, co może również pomóc w wydajności.


2

Widziałem znaczny wzrost wydajności dzięki użyciu EnsureCapacity(int capacity)wywołania metody w instancji StringBuilderprzed użyciem go do przechowywania ciągów znaków. Zwykle nazywam to w wierszu kodu po utworzeniu wystąpienia. Ma taki sam efekt, jakbyś utworzył taką instancję StringBuilder:

var sb = new StringBuilder(int capacity);

To połączenie alokuje potrzebną pamięć z wyprzedzeniem, co powoduje mniej alokacji pamięci podczas wielu Append()operacji. Musisz zgadnąć, ile pamięci potrzebujesz, ale w przypadku większości aplikacji nie powinno to być zbyt trudne. Zwykle mylę się po stronie trochę za dużej pamięci (mówimy około 1k).


Nie trzeba dzwonić EnsureCapacitybezpośrednio po StringBuilderutworzeniu instancji. Po prostu instancję StringBuildertak: var sb = new StringBuilder(int capacity).
David Ferenczy Rogožan

Powiedziano mi, że pomaga użyć liczby pierwszej.
Karl Gjertsen

1

W nawiązaniu do poprzednich odpowiedzi, pierwszą rzeczą, którą zawsze robię, gdy myślę o takich sprawach, jest stworzenie małej aplikacji testowej. Wewnątrz tej aplikacji wykonaj test czasowy dla obu scenariuszy i przekonaj się, co jest szybsze.

IMHO, dołączając ponad 500 wpisów w łańcuchach, zdecydowanie należy użyć StringBuilder.


1

String i StringBuilder są w rzeczywistości niezmienne, StringBuilder ma wbudowane bufory, które pozwalają na bardziej efektywne zarządzanie jego rozmiarem. Kiedy StringBuilder musi zmienić rozmiar, następuje ponowne przydzielenie go na stercie. Domyślnie ma wielkość 16 znaków, możesz ustawić to w konstruktorze.

na przykład.

StringBuilder sb = new StringBuilder (50);


2
Nie jestem pewien, czy rozumiesz, co oznacza niezmienny. Ciągi są niezmienne, NIE MOŻNA ich zmienić. Wszystko, co „zmieniono”, polega na tym, że stara wartość pozostaje na stercie bez ŻADNEGO wskaźnika do jej zlokalizowania. StringBuilder (mutable) to typ odwołania na stercie, wskaźnik na stercie jest zmieniany i przydział miejsca dla tej zmiany.
Tom Stickel,

1

Łączenie łańcuchów będzie cię kosztować więcej. W Javie możesz użyć StringBuffer lub StringBuilder w zależności od potrzeb. Jeśli chcesz zsynchronizowaną i bezpieczną dla wątków implementację, wybierz StringBuffer. Będzie to szybsze niż konkatenacja ciągów.

Jeśli nie potrzebujesz implementacji synchronicznej lub bezpiecznej dla wątków, wybierz StringBuilder. Będzie to szybsze niż konkatenacja String, a także szybsze niż StringBuffer, ponieważ nie jest to narzut związany z synchronizacją.


0

StringBuilder jest prawdopodobnie preferowany. Powodem jest to, że przydziela więcej miejsca niż obecnie potrzebne (ustawiasz liczbę znaków), aby zostawić miejsce na przyszłe dodatki. Następnie te przyszłe załączniki, które mieszczą się w bieżącym buforze, nie wymagają alokacji pamięci ani odśmiecania, co może być kosztowne. Zasadniczo używam StringBuilder do łączenia złożonych łańcuchów lub formatowania wielokrotnego, a następnie przekształcam się w normalny ciąg znaków, gdy dane są kompletne, i chcę ponownie obiektu niezmiennego.


0

Jeśli wykonujesz dużo łączenia łańcuchów, użyj StringBuilder. Podczas łączenia z ciągiem za każdym razem tworzony jest nowy ciąg, zużywając więcej pamięci.

Alex


0

Zasadą ogólną jest to, że jeśli muszę ustawić wartość ciągu więcej niż jeden raz lub jeśli ciąg jest dołączany, to musi to być kreator ciągu. Widziałem aplikacje, które napisałem w przeszłości, zanim dowiedziałem się o konstruktorach łańcuchów, które miały ogromny ślad pamięci, który po prostu wydaje się stale rosnąć. Zmiana tych programów na użycie konstruktora ciągów znacznie zmniejsza zużycie pamięci. Teraz przysięgam na konstruktora strun.



0

StringBuilder jest znacznie bardziej wydajny, ale nie zobaczysz tej wydajności, chyba że wykonasz dużą ilość modyfikacji łańcucha.

Poniżej znajduje się krótki fragment kodu, który stanowi przykład wydajności. Jak widać, naprawdę zaczyna się zauważać znaczny wzrost wydajności, gdy przejdziesz do dużych iteracji.

Jak widać, 200 000 iteracji zajęło 22 sekundy, podczas gdy 1 milion iteracji z użyciem tego StringBuilderbyło prawie natychmiastowe.

string s = string.Empty;
StringBuilder sb = new StringBuilder();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 50000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();

Console.WriteLine("Beginning String + at " + DateTime.Now.ToString());

for (int i = 0; i <= 200000; i++)
{
    s = s + 'A';
}

Console.WriteLine("Finished String + at " + DateTime.Now.ToString());
Console.WriteLine();
Console.WriteLine("Beginning Sb append at " + DateTime.Now.ToString());

for (int i = 0; i <= 1000000; i++)
{
    sb.Append("A");
}
Console.WriteLine("Finished Sb append at " + DateTime.Now.ToString());

Console.ReadLine();

Wynik powyższego kodu:

Początkowy ciąg + o 28.01.2013 16:55:40.

Ukończony ciąg + na 28.01.2013 16:55:40.

Początkowy ciąg + o 28.01.2013 16:55:40.

Ukończony ciąg + na 28.01.2013 16:56:02.

Początek Sb dołączamy o 28.01.2013 16:56:02.

Gotowe Sb dołączają o 28.01.2013 16:56:02.


1
Jeśli Konstruktor ciągów jest tak potężny, to dlaczego istnieje Ciąg. Dlaczego nie całkowicie usuniemy String. Zadałem to pytanie, abyś mógł mi powiedzieć, ZALETĘ Stringa nad StringBuilder
Unbreakable

-2

StringBuilder będzie działał lepiej, z punktu widzenia pamięci. Jeśli chodzi o przetwarzanie, różnica w czasie wykonania może być nieznaczna.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.