Ponieważ nie sądzę, aby odpowiedzi tutaj obejmowały wszystko, chciałbym dodać tutaj mały dodatek.
Console.WriteLine(string format, params object[] pars)
wezwania string.Format
. Znak „+” oznacza konkatenację ciągów. Nie sądzę, że zawsze ma to związek ze stylem; Zwykle mieszam te dwa style w zależności od kontekstu, w którym się znajduję.
Krótka odpowiedź
Decyzja, przed którą stoisz, ma związek z alokacją ciągów. Postaram się to uprościć.
Powiedz, że masz
string s = a + "foo" + b;
Jeśli to wykonasz, oceni to w następujący sposób:
string tmp1 = a;
string tmp2 = "foo"
string tmp3 = concat(tmp1, tmp2);
string tmp4 = b;
string s = concat(tmp3, tmp4);
tmp
tutaj nie jest tak naprawdę zmienną lokalną, ale jest ona tymczasowa dla JIT (jest umieszczana na stosie IL). Jeśli ldstr
umieścisz łańcuch na stosie (na przykład w IL dla literałów), umieszczasz odwołanie do wskaźnika ciągu na stosie.
Moment wywołania concat
tego odwołania staje się problemem, ponieważ nie ma żadnego dostępnego odwołania do łańcucha, które zawiera oba ciągi. Oznacza to, że .NET musi przydzielić nowy blok pamięci, a następnie wypełnić go dwoma ciągami. Powodem tego jest problem, ponieważ alokacja jest stosunkowo droga.
Co zmienia pytanie na: Jak zmniejszyć liczbę concat
operacji?
Tak więc przybliżona odpowiedź brzmi: string.Format
dla> 1 konkatacji „+” będzie działać dobrze na 1 konkat. A jeśli nie zależy ci na wykonywaniu mikrooptymalizacji wydajności, string.Format
w ogólnym przypadku będzie działać dobrze.
Uwaga o kulturze
A potem jest coś, co nazywa się kulturą ...
string.Format
umożliwia korzystanie CultureInfo
w formatowaniu. Prosty operator „+” używa bieżącej kultury.
Jest to szczególnie ważna uwaga, jeśli piszesz formaty plików i np. double
wartości, które „dodajesz” do ciągu. Na różnych komputerach możesz skończyć z różnymi łańcuchami, jeśli nie używaszstring.Format
z jawnym CultureInfo
.
F.ex. zastanów się, co się stanie, jeśli zmienisz „.” zamiast „,” podczas pisania pliku z wartościami oddzielonymi przecinkami ... w języku holenderskim separatorem dziesiętnym jest przecinek, więc użytkownik może po prostu otrzymać „zabawną” niespodziankę.
Bardziej szczegółowa odpowiedź
Jeśli nie znasz wcześniej dokładnego rozmiaru łańcucha, najlepiej użyć takiej zasady, aby nadać przydział buforów, których używasz. Wolna przestrzeń jest najpierw wypełniana, po czym dane są kopiowane.
Powiększanie oznacza przydzielanie nowego bloku pamięci i kopiowanie starych danych do nowego bufora. Następnie można zwolnić stary blok pamięci. W tym momencie dochodzisz do wniosku: uprawa to kosztowna operacja.
Najbardziej praktycznym sposobem na to jest użycie zasad nadmiernej alokacji. Najbardziej powszechną polityką jest nadawanie buforów potęgom 2. Oczywiście musisz to zrobić trochę mądrzej (ponieważ nie ma sensu rosnąć z 1,2,4,8 jeśli już wiesz, że potrzebujesz 128 znaków ), ale masz obraz. Polityka zapewnia, że nie potrzebujesz zbyt wielu kosztownych operacji, które opisałem powyżej.
StringBuilder
jest klasą, która w zasadzie z nadmierną alokacją bazowego bufora potęgami dwóch. string.Format
używa StringBuilder
pod maską.
To sprawia, że Twoja decyzja jest podstawowym kompromisem między nadmierną alokacją i dołączaniem (-multiple) (w / wo culture) lub po prostu przydziel i dołącz.
string.Format
które nie używa żadnych funkcji formatowania kompozytowego (tj. Jest po prostu proste{0}
) i zastępuje je znacznie szybszą konkatenacją ciągów. Zastanawiam się, że taki wyczyn jest możliwy do osiągnięcia przy użyciu istniejącego narzędzia do ponownego pisania IL, takiego jak PostSharp.