Frage

Meine Frage lautet: String-Verkettung in C # sicher ist? Wenn die String-Verkettung zu unerwarteten Fehlern führt, und dass die String-Verkettung ersetzt durch String mit verursacht diese Fehler verschwinden, was könnte das an?

Hintergrund: Ich bin eine kleine Kommandozeile C # .NET-Anwendung zu entwickeln. Es dauert Befehlszeilenargumente, führt eine etwas komplizierte SQL-Abfrage und gibt etwa 1300 Zeilen von Daten in eine formatierte XML-Datei.

Mein erstes Programm würde immer laufen im Debug-Modus in Ordnung. im Release-Modus würde es über das 750. SQL Ergebnis erhält aber, und dann mit einem Fehler sterben. Der Fehler war, dass eine bestimmte Spalte von Daten nicht gelesen werden kann, auch durch die Read () -Methode des SqlDataReader Objekts hatte gerade wieder wahr.

Dieses Problem wurde durch die Verwendung Stringbuilder für alle Operationen im Code festgelegt, wo früher „string1 + string2“ gewesen. Ich spreche nicht über die String-Verkettung innerhalb der SQL-Abfrage-Schleife, wo String war bereits im Einsatz. Ich spreche über einfache Verkettungen zwischen zwei oder drei kurzen String-Variablen früher im Code.

hatte ich den Eindruck, dass C # klug genug war für das Hinzufügen von ein paar Fäden zusammen, um die Speicherverwaltung zu handhaben. Liege ich falsch? Oder ist dies eine andere Art von Code Problem hinweisen?

War es hilfreich?

Lösung

Neben was Sie tun, ist wahrscheinlich am besten mit XML-APIs erfolgt anstelle von Strings oder String Ich bezweifle, dass der Fehler, den Sie sehen, String-Verkettung zurückzuführen ist. Vielleicht Stringschalt maskiert nur den Fehler oder ging anmutig über sie, aber ich bezweifle, Streicher war wirklich die Ursache verwendet wird.

Andere Tipps

Ihre Frage zu beantworten: String contatenation in C # (und .NET im Allgemeinen) ist „sicher“, aber es in einer engen Schleife zu tun, wie Sie beschreiben, sind wahrscheinlich schweren Speicherdruck verursachen und setzt Belastung für den Garbage Collector.

Ich würde eine Vermutung Gefahr, dass die Fehler, die Sie von im Zusammenhang sprechen waren Erschöpfung von einer Art Ressource, aber es wäre hilfreich, wenn Sie mehr Details liefern könnten - zum Beispiel, haben erhalten Sie eine Ausnahme? Hat die Anwendung abnormal beenden?

Hintergrund: .NET-Strings sind unveränderlich, also, wenn Sie tun, um eine Verkettung wie folgt aus:

var stringList = new List<string> {"aaa", "bbb", "ccc", "ddd", //... };
string result = String.Empty;
foreach (var s in stringList)
{
    result = result + s;
}

Dies entspricht in etwa wie folgt vor:

string result = "";
result = "aaa"
string temp1 = result + "bbb";
result = temp1;
string temp2 = temp1 + "ccc";
result = temp2;
string temp3 = temp2 + "ddd";
result = temp3;
// ...
result = tempN + x;

Der Zweck dieses Beispiels ist, dass jedes Mal, um die Schleife Ergebnisse bei der Zuweisung eines neuen temporären String hervorzuheben.

Da die Saiten unveränderlich sind, die Laufzeit hat keine Alternativen, sondern eine neue Zeichenfolge jedes Mal, wenn Sie eine andere Zeichenfolge fügen dem Ende Ihres Ergebnis zuzuweisen.

Obwohl der result String wird ständig aktualisiert, um das neueste und beste Zwischenergebnis zu zeigen, führen Sie eine Menge von diesem un-named temporären String erzeugen, die fast sofort für die Garbage Collection geeignet werden.

Am Ende dieser Verkettung Sie die folgenden Zeichenfolgen in einem Speicher gespeichert wird (unter der Annahme, der Einfachheit halber, dass der Garbage Collector noch nicht ausgeführt wurde).

string a = "aaa";
string b = "bbb";
string c = "ccc";
// ...
string temp1 = "aaabbb";
string temp2 = "aaabbbccc";
string temp3 = "aaabbbcccddd";
string temp4 = "aaabbbcccdddeee";
string temp5 = "aaabbbcccdddeeefff";
string temp6 = "aaabbbcccdddeeefffggg";
// ...

Obwohl alle diese impliziten temporären Variablen in Betracht kommen für die Garbage Collection fast sofort, sie haben immer noch zugeteilt werden. Wenn Verkettung in einer engen Schleife durchführt, das wird viel Belastung auf den Garbage Collector setzen und, wenn nichts anderes, wird Ihr Code machen sehr langsam laufen. Ich habe die Auswirkungen auf die Leistung dieser aus erster Hand zu sehen ist, und es wird wirklich dramatisch als verkettete Zeichenfolge größer wird.

Die empfohlene Vorgehensweise ist immer eine StringBuilder zu verwenden, wenn Sie mehr als ein paar String-Verkettungen tun. StringBuilder einen wandelbaren Puffer verwendet die Anzahl der Zuweisungen zu reduzieren, die beim Aufbau der Zeichenfolge notwendig sind.

String-Verkettung ist sicher, obwohl speicherintensiver als ein String verwenden, wenn contatenating eine große Anzahl von Zeichenketten in einer Schleife. Und in extremen Fällen Sie aus dem Speicher werden könnten ausgeführt wird.

Es ist mit ziemlicher Sicherheit um einen Fehler im Code.

Vielleicht sind contatenating Sie eine sehr große Anzahl von Strings. Oder vielleicht ist es etwas anderes, ganz anders aus.

Ich würde ohne Vorurteile der Ursache zu Debuggen zurückgehen - wenn Sie immer noch Probleme haben versuchen Sie es erforderlich, um ein Minimum zu reduzieren, das Problem und Postleitzahl repro

.

Wie lange würde es die Verkettung Version vs der String-Builder-Version nehmen? Es ist möglich, dass die Verbindung zum DB geschlossen wird. Wenn Sie eine Menge Verkettung tun, würde ich mich w / String weil es etwas effizienter ist.

Eine Ursache kann sein, dass Strings in .Net so unveränderlich sind, wenn Sie eine Operation zu tun auf der einen wie Verkettung sind Sie tatsächlich eine neue Zeichenfolge zu erstellen.

Eine weitere mögliche Ursache ist, dass String-Länge ist ein int so die maximal mögliche Länge Int32.MaxValue oder 2,147,483,647 ist.

In jedem Fall ein String ist besser als „string1 + string2“ für diese Art von Operation. Obwohl, wäre es, die integrierten XML-Funktionen mit noch besser.

string.Concat(string[]) ist bei weitem der schnellste Weg, Strings zu verketten. Es tötet litterly StringBuilder in Leistung, wenn in Schleifen verwendet, besonders wenn man die StringBuilder in jeder Iteration erstellen. Es gibt viele Referenzen, wenn Sie „c # String-Format vs Stringbuilder“ Google oder so ähnlich. http://www.codeproject.com/KB/cs/StringBuilder_vs_String.aspx gibt Ihnen einen ideer über die Zeiten. Hier string.Join gewinnt die Verkettung Test, aber ich glaube das ist, weil die string.Concat(string, string) anstelle der überladene Version verwendet wird, die ein Array nimmt. Wenn man sich den MSIL-Code einen Blick darauf werfen, die von den verschiedenen Methoden erzeugt wird, werden Sie sehen, was unter der Haube geht.

Hier ist mein Schuss im Dunkeln ...

Strings in .NET (nicht Stringbuilders) gehen in den String Intern Pool. Dies ist im Grunde ein Bereich von der CLR verwaltet Strings teilt die Leistung zu verbessern. Es muss eine Grenze, hier sein, obwohl ich keine Ahnung, was die Grenze ist. Ich stelle mir die ganze Verkettung Sie tun, ist die Decke des Strings intern Pool schlagen. So sagt SQL ja, ich habe einen Wert für Sie, aber es kann nicht überall setzen, so dass Sie eine Ausnahme erhalten.

Ein schneller und einfacher Test wäre Talisma Ihre Montage und sehen, ob Sie noch die Störung. Nach nGen'ing finden Sie Anwendung nicht mehr auf den Pool nutzen.

Wenn das fehlschlägt, würde ich an Microsoft wenden, um zu versuchen und einige harten Details. Ich glaube, meine Idee klingt plausibel, aber ich habe keine Ahnung, warum es im Debug-Modus arbeitet. Vielleicht im Debug-Modus Strings werden nicht interniert. Ich bin auch kein Experte.

Wenn Strings zusammen Compoundierung ich immer String verwenden. Es ist für sie entworfen und ist effizienter, dass einfach „string1 + string2“ verwendet wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top