Wie viele String-Objekte werden erstellt, wenn im folgenden Code ein Pluszeichen verwendet wird?
String result = "1" + "2" + "3" + "4";
Wenn es wie folgt wäre, hätte ich drei String-Objekte gesagt: "1", "2", "12".
String result = "1" + "2";
Ich weiß auch, dass String-Objekte zur Verbesserung der Leistung im String Intern Pool / Table zwischengespeichert werden, aber das ist nicht die Frage.
Antworten:
Überraschenderweise kommt es darauf an.
Wenn Sie dies in einer Methode tun:
dann scheint der Compiler den Code mit der
String.Concat
Antwort von @Joachim (+1 an ihn übrigens) auszugeben.Wenn Sie sie als Konstanten definieren , z.
oder als Literale , wie in der ursprünglichen Frage:
dann optimiert der Compiler diese
+
Zeichen. Es ist äquivalent zu:Darüber hinaus entfernt der Compiler überflüssige konstante Ausdrücke und gibt sie nur aus, wenn sie verwendet oder verfügbar gemacht werden. Zum Beispiel dieses Programm:
Erzeugt nur eine Zeichenfolge - die Konstante
result
(gleich "1234").one
undtwo
erscheinen nicht in der resultierenden IL.Beachten Sie, dass zur Laufzeit möglicherweise weitere Optimierungen vorgenommen werden. Ich gehe nur nach dem, was IL produziert.
In Bezug auf die Internierung werden schließlich Konstanten und Literale interniert, aber der Wert, der interniert wird, ist der resultierende konstante Wert in der IL, nicht das Literal. Dies bedeutet, dass Sie möglicherweise noch weniger Zeichenfolgenobjekte als erwartet erhalten, da mehrere identisch definierte Konstanten oder Literale tatsächlich dasselbe Objekt sind! Dies wird durch Folgendes veranschaulicht:
In dem Fall, in dem Zeichenfolgen in einer Schleife (oder auf andere Weise dynamisch) verkettet werden, erhalten Sie eine zusätzliche Zeichenfolge pro Verkettung. Im Folgenden werden beispielsweise 12 Zeichenfolgeninstanzen erstellt: 2 Konstanten + 10 Iterationen, die jeweils zu einer neuen Zeichenfolgeninstanz führen:
Aber (auch überraschend) werden mehrere aufeinanderfolgende Verkettungen vom Compiler zu einer einzigen Verkettung mit mehreren Zeichenfolgen kombiniert. Zum Beispiel erzeugt dieses Programm auch nur 12 String-Instanzen! Dies liegt daran, dass " Selbst wenn Sie mehrere + -Operatoren in einer Anweisung verwenden, der Zeichenfolgeninhalt nur einmal kopiert wird. "
quelle
string s = ""; for (int i = 0; i < n; i++) s += "a";
Chris Shains Antwort ist sehr gut. Als die Person, die den Optimierer für die Verkettung von Zeichenfolgen geschrieben hat, möchte ich nur zwei weitere interessante Punkte hinzufügen.
Das erste ist, dass der Verkettungsoptimierer im Wesentlichen beide Klammern und die linke Assoziativität ignoriert, wenn dies sicher möglich ist. Angenommen, Sie haben eine Methode M (), die eine Zeichenfolge zurückgibt. Wenn du sagst:
dann begründet der Compiler, dass der Additionsoperator assoziativ bleibt, und daher ist dies dasselbe wie:
Aber dieses:
ist das gleiche wie
Das ist also die Verkettung der konstanten Zeichenfolge
"CD"
mitM()
.Tatsächlich erkennt der Verkettungsoptimierer, dass die Verkettung von Zeichenfolgen assoziativ ist , und generiert
String.Concat(M(), "AB")
für das erste Beispiel, obwohl dies die linke Assoziativität verletzt.Sie können dies sogar tun:
und wir werden immer noch generieren
String.Concat(M(), "EF", M())
.Der zweite interessante Punkt ist, dass null und leere Zeichenfolgen weg optimiert werden. Wenn Sie dies tun:
Du wirst kriegen
String.Concat(M(), M())
Dann stellt sich eine interessante Frage: Was ist damit?
Wir können das nicht bis auf optimieren
da
M()
könnte null zurückgeben,String.Concat(M(), null)
würde aber eine leere Zeichenfolge zurückgeben, wennM()
null zurückgegeben wird. Also reduzieren wir stattdessenzu
Dadurch wird gezeigt, dass die Verkettung von Zeichenfolgen überhaupt nicht aufgerufen werden muss
String.Concat
.Weitere Informationen zu diesem Thema finden Sie unter
Warum ist String.Concat nicht für StringBuilder.Append optimiert?
quelle
("C" + "D") + M())
erzeugtString.Concat("CD", M())
, nichtString.Concat(M(), "AB")
. Und weiter unten,(M() + "E") + (null + M())
sollte erzeugenString.Concat(M(), "E", M())
, nichtString.Concat(M(), M())
.Ich habe die Antwort bei MSDN gefunden. Einer.
Gewusst wie: Verketten mehrerer Zeichenfolgen (C # -Programmierhandbuch)
quelle
Nur einer. Der C # -Compiler faltet Zeichenfolgenkonstanten und kompiliert daher im Wesentlichen bis zu
quelle
Ich bezweifle, dass dies durch einen Standard oder eine Spezifikation vorgeschrieben ist. Eine Version kann wahrscheinlich etwas anderes als eine andere.
quelle
Erstens, da sie statisch sind, kann der Compiler sie zur Kompilierungszeit auf eine einzelne Zeichenfolge optimieren.
Wenn sie dynamisch gewesen wären , wären sie für einen einzelnen Aufruf von String.Concat (Zeichenfolge, Zeichenfolge, Zeichenfolge, Zeichenfolge) optimiert worden .
quelle