Ich verstehe die Vorteile von StringBuilder.
Wenn ich jedoch 2 Zeichenfolgen verketten möchte, gehe ich davon aus, dass es besser (schneller) ist, dies ohne StringBuilder zu tun. Ist das richtig?
Ab wann (Anzahl der Zeichenfolgen) ist es besser, StringBuilder zu verwenden?
c#
stringbuilder
Shiraz Bhaiji
quelle
quelle
Antworten:
Ich empfehle Ihnen wärmstens, die traurige Tragödie des Mikrooptimierungstheaters von Jeff Atwood zu lesen .
Es behandelt Simple Concatenation vs. StringBuilder vs. andere Methoden.
Wenn Sie nun einige Zahlen und Grafiken sehen möchten, folgen Sie dem Link;)
quelle
Das ist in der Tat richtig, Sie können herausfinden, warum genau sehr gut erklärt auf:
http://www.yoda.arachsys.com/csharp/stringbuilder.html
Zusammenfassend: Wenn Sie Saiten auf einmal zusammenfassen können, gehen Sie wie
var result = a + " " + b + " " + c + ..
Sie sind ohne StringBuilder besser dran, da nur eine Kopie erstellt wird (die Länge der resultierenden Zeichenfolge wird zuvor berechnet.);
Für Struktur wie
var result = a; result += " "; result += b; result += " "; result += c; ..
Jedes Mal werden neue Objekte erstellt, daher sollten Sie dort StringBuilder in Betracht ziehen.
Am Ende fasst der Artikel folgende Faustregeln zusammen:
quelle
System.String ist ein unveränderliches Objekt. Dies bedeutet, dass bei jeder Änderung des Inhalts eine neue Zeichenfolge zugewiesen wird. Dies kostet Zeit (und Speicher?). Mit StringBuilder ändern Sie den tatsächlichen Inhalt des Objekts, ohne einen neuen zuzuweisen.
Verwenden Sie StringBuilder, wenn Sie viele Änderungen an der Zeichenfolge vornehmen müssen.
quelle
Nicht wirklich ... Sie sollten StringBuilder verwenden, wenn Sie große Zeichenfolgen verketten oder wenn Sie viele Verkettungen haben, wie in einer Schleife.
quelle
StringBuilder
nur verwenden, wenn die Schleife oder die Verkettung ein Leistungsproblem für die Spezifikationen darstellt.string s = "abcd"
, zumindest ist das das Letzte Ich habe gehört ... aber mit Variablen wäre es höchstwahrscheinlich Concat.a + "hello" + "somethingelse"
und musste mich nie darum kümmern. Wenn es zu einem Problem wird, verwende ich StringBuilder. Aber ich habe mir überhaupt keine Sorgen gemacht und weniger Zeit damit verbracht, es zu schreiben.Hier ist eine einfache Test-App, um den Punkt zu beweisen:
class Program { static void Main(string[] args) { const int testLength = 30000; var StartTime = DateTime.Now; //TEST 1 - String StartTime = DateTime.Now; String tString = "test string"; for (int i = 0; i < testLength; i++) { tString += i.ToString(); } Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString()); //result: 2000 ms //TEST 2 - StringBuilder StartTime = DateTime.Now; StringBuilder tSB = new StringBuilder("test string"); for (int i = 0; i < testLength; i++) { tSB.Append(i.ToString()); } Console.WriteLine((DateTime.Now - StartTime).TotalMilliseconds.ToString()); //result: 4 ms Console.ReadLine(); } }
Ergebnisse:
30'000 Iterationen
1000 Iterationen
500 Iterationen
quelle
Umschreiben
Im Allgemeinen verwende ich den String Builder für jeden Codeblock, der zur Verkettung von drei oder mehr Strings führen würde.
quelle
Es gibt keine endgültige Antwort, nur Faustregeln. Meine persönlichen Regeln lauten ungefähr so:
StringBuilder
.StringBuilder
.Wenn nicht, verwenden Sie a
StringBuilder
.quelle
Ja. Noch wichtiger ist jedoch , dass die Verwendung einer Vanille in solchen Situationen weitaus besser lesbar ist
String
. Die Verwendung in einer Schleife ist dagegen sinnvoll und kann ebenso lesbar sein wie die Verkettung.Ich würde mich vor Faustregeln hüten, die eine bestimmte Anzahl von Verkettungen als Schwelle angeben. Die Verwendung in Schleifen (und nur in Schleifen) ist wahrscheinlich genauso nützlich, leichter zu merken und sinnvoller.
quelle
Solange Sie die Anzahl der Verkettungen (a + b + c ...) physisch eingeben können, sollte dies keinen großen Unterschied machen. N im Quadrat (bei N = 10) ist eine 100-fache Verlangsamung, die nicht schlecht sein sollte.
Das große Problem ist, wenn Sie Hunderte von Zeichenfolgen verketten. Bei N = 100 erhalten Sie eine 10000-fache Verlangsamung. Welches ist ziemlich schlecht.
quelle
Da es schwierig ist, eine Erklärung dafür zu finden, die weder von Meinungen beeinflusst noch von einem Kampf der Stolz gefolgt wird, habe ich mir überlegt, ein bisschen Code auf LINQpad zu schreiben, um dies selbst zu testen.
Ich fand heraus, dass die Verwendung kleiner Zeichenfolgen anstelle von i.ToString () die Antwortzeiten ändert (sichtbar in kleinen Schleifen).
Der Test verwendet verschiedene Iterationssequenzen, um Zeitmessungen in vernünftig vergleichbaren Bereichen zu halten.
Ich werde den Code am Ende kopieren, damit Sie ihn selbst ausprobieren können (results.Charts ... Dump () funktioniert außerhalb von LINQPad nicht).
Ausgabe (X-Achse: Anzahl der getesteten Iterationen, Y-Achse: Zeit in Ticks):
Iterationssequenz: 2, 3, 4, 5, 6, 7, 8, 9, 10
Iterationssequenz: 10, 20, 30, 40, 50, 60, 70, 80
Iterationssequenz: 100, 200, 300, 400, 500
Code (geschrieben mit LINQPad 5):
void Main() { Test(2, 3, 4, 5, 6, 7, 8, 9, 10); Test(10, 20, 30, 40, 50, 60, 70, 80); Test(100, 200, 300, 400, 500); } void Test(params int[] iterationsCounts) { $"Iterations sequence: {string.Join(", ", iterationsCounts)}".Dump(); int testStringLength = 10; RandomStringGenerator.Setup(testStringLength); var sw = new System.Diagnostics.Stopwatch(); var results = new Dictionary<int, TimeSpan[]>(); // This call before starting to measure time removes initial overhead from first measurement RandomStringGenerator.GetRandomString(); foreach (var iterationsCount in iterationsCounts) { TimeSpan elapsedForString, elapsedForSb; // string sw.Restart(); var str = string.Empty; for (int i = 0; i < iterationsCount; i++) { str += RandomStringGenerator.GetRandomString(); } sw.Stop(); elapsedForString = sw.Elapsed; // string builder sw.Restart(); var sb = new StringBuilder(string.Empty); for (int i = 0; i < iterationsCount; i++) { sb.Append(RandomStringGenerator.GetRandomString()); } sw.Stop(); elapsedForSb = sw.Elapsed; results.Add(iterationsCount, new TimeSpan[] { elapsedForString, elapsedForSb }); } // Results results.Chart(r => r.Key) .AddYSeries(r => r.Value[0].Ticks, LINQPad.Util.SeriesType.Line, "String") .AddYSeries(r => r.Value[1].Ticks, LINQPad.Util.SeriesType.Line, "String Builder") .DumpInline(); } static class RandomStringGenerator { static Random r; static string[] strings; public static void Setup(int testStringLength) { r = new Random(DateTime.Now.Millisecond); strings = new string[10]; for (int i = 0; i < strings.Length; i++) { strings[i] = Guid.NewGuid().ToString().Substring(0, testStringLength); } } public static string GetRandomString() { var indx = r.Next(0, strings.Length); return strings[indx]; } }
quelle
Ich glaube nicht, dass es eine feine Linie zwischen dem Zeitpunkt und dem Nichtgebrauch gibt. Es sei denn natürlich, jemand hat einige umfangreiche Tests durchgeführt, um mit den goldenen Bedingungen herauszukommen.
Für mich werde ich StringBuilder nicht verwenden, wenn ich nur 2 große Zeichenfolgen verkette. Wenn es eine Schleife mit einer nicht deterministischen Anzahl gibt, bin ich es wahrscheinlich, auch wenn die Schleife eine kleine Anzahl sein könnte.
quelle
Eine einzelne Verkettung lohnt sich nicht mit einem StringBuilder. Ich habe normalerweise 5 Verkettungen als Faustregel verwendet.
quelle