2008-09-26 14 views
186

Was ist die längste Zeichenfolge, die in .NET erstellt werden kann? Die Dokumente für die Klasse String sind in dieser Frage, soweit ich sehen kann, still, so dass eine autoritative Antwort einige Kenntnisse der Interna erfordern kann. Würde sich die maximale Änderung auf einem 64-Bit-System ändern?Was ist die maximal mögliche Länge einer .NET-Zeichenfolge?

[Dies ist mehr für Neugier gefragt als für den praktischen Gebrauch - Ich beabsichtige nicht, einen Code zu erstellen, die gigantische Strings]

Antwort

270

Die theoretische Grenze kann 2,147,483,647 sein, aber die praktische Grenze ist nicht annähernd. Da kein einzelnes Objekt in einem .Net-Programm mehr als 2 GB groß sein darf und der Zeichenkettentyp Unicode verwendet (2 Bytes für jedes Zeichen), ist das Beste, was Sie tun können, 1.073.741.823, aber Sie werden wahrscheinlich nicht in der Lage sein, das auf einem zu verteilen 32-Bit-Maschine. Diese

ist eine jener Situationen, in denen "If you have to ask, you're probably doing something wrong."

+7

Dies ist die richtige Antwort. Es ist wahrscheinlicher, dass Ihnen der Speicher ausgeht, bevor Sie genügend Speicherplatz zuweisen können, um die Zeichenfolgenlänge zu nutzen. Bei einem Neustart können Sie möglicherweise eine Zuweisung von 2 GB (mit 1 Mio. Zeichen) wie hier erwähnt abrufen, aber das ist alles. –

+4

Unter der Annahme, dass Ihre Behauptung "kein einzelnes Objekt kann über 2 GB sein" korrekt ist, ist dies sowohl die theoretische als auch die praktische Grenze - die Einschränkung für die Stringlänge wäre die gesamte Objektgröße, nicht die Kapazität des Längenfelds. – McKenzieG1

+10

Wenn sich jemand für den genauen Wert interessiert, sind es auf meinem 64-Bit-Gerät 1.073.741.791 (1024 · 1024 · 1024 - 33) Zeichen. Siehe auch [meine verwandte Frage über die genaue maximale Größe von 'byte []'] (http://stackoverflow.com/q/6616739/41071). – svick

47

Da die Eigenschaft Länge von System.String ist ein Int32, ich würde vermuten, dass die maximale Länge 2.147.483.647 Zeichen (max Int32 Größe) wäre. Wenn es länger erlaubte, konnte man die Länge nicht überprüfen, da dies fehlschlagen würde.

+10

+1 Guten Abzug –

+2

@ m.edmondson: Ich bin eigentlich nicht überzeugt. Ein [Array] (https://msdn.microsoft.com/en-us/library/system.array%28v=vs.110%29.aspx) für Instanzen hat auch eine 'LongLength' und ein Stream' 'long 'als Länge. Obwohl es eine gültige Antwort ist, ist es eine genaue Methode, dies zu messen. –

+0

Aber die ersten zwei Bits werden für ASCII/Nicht-ASCII-Indikation verwendet, wie [dieser Artikel] (https://www.codeproject.com/Articles/3377/Strings-UNDOCUMENTED) sagt, also sollte es 2^30 = 1 sein 073 741 824 – Saito

0

Da String.length eine ganze Zahl (die ein Alias ​​für Int32 ist) um seine Größe zu Int32.MaxValue Unicode-Zeichen beschränkt ist;)

60

Aufgrund meines sehr wissenschaftlichen und genaues Experiment, Tops es auf meinem Rechner aus gut vor 1.000.000.000 Zeichen (ich führe immer noch den unten stehenden Code aus, um einen besseren Pinpoint zu erhalten). UPDATE: Nach ein paar Stunden habe ich aufgegeben. Endergebnis: Kann viel größer als 100.000.000 Zeichen werden und sofort System.OutOfMemoryException bei 1.000.000.000 Zeichen erhalten.

using System; 
using System.Collections.Generic; 

public class MyClass 
{ 
    public static void Main() 
    { 
     int i = 100000000; 
     try 
     { 
      for (i = i; i <= int.MaxValue; i+= 5000) 
      { 
       string value = new string('x', i); 
       //WL(i); 
      } 
     } 
     catch (Exception exc) 
     { 
      WL(i); 
      WL(exc); 
     } 
     WL(i); 
     RL(); 
    } 

    #region Helper methods 

    private static void WL(object text, params object[] args) 
    { 
     Console.WriteLine(text.ToString(), args); 
    } 

    private static void RL() 
    { 
     Console.ReadLine(); 
    } 

    private static void Break() 
    { 
     System.Diagnostics.Debugger.Break(); 
    } 

    #endregion 
} 
+25

Das Anwenden einer binären Suche hier würde Ihnen wahrscheinlich helfen, diese Antwort viel schneller zu finden ... – Mario

+24

+1 für die Verwendung von testgesteuerten Antworten. –

1

200 MB ..., an dem Ihre App verweisen auf eine virtuelle Stocken gerät, hat etwa ein Konzert Arbeitssatzspeicher und die o/s beginnt wie Sie zu handeln Ich muss neu starten.

static void Main(string[] args) 
{ 
    string s = "hello world"; 
    for(;;) 
    { 
     s = s + s.Substring(0, s.Length/10); 
     Console.WriteLine(s.Length); 
    } 
} 

12 
13 
14 
15 
16 
17 
18 
... 
158905664 
174796230 
192275853 
211503438 
+4

Ich bin mir nicht sicher, ob das Verhalten, das man beim Erstellen einer wirklich großen Zeichenfolge erhält, dasselbe ist wie das, was man sieht, indem man eine Menge von ihnen zuordnet und verkettet. – Casey

20

Für alle zu diesem späten Thema kommen, könnte ich das hitscan sehen, „sollten Sie wahrscheinlich nicht tun, dass“ jemand fragen verursachen könnten, was sie tun sollten ...

DIe StringBuilder Klasse ist oft ein einfacher Ersatz. Betrachten Sie eine der stream-based classes vor allem, wenn Ihre Daten aus einer Datei stammen.

Das Problem mit s = s + "stuff" ist, dass es einen komplett neuen Bereich zuweisen muss, um die Daten zu halten und dann alle alten Daten plus das neue Zeug - JEDER LOOP ITERATION. Das Hinzufügen von 5 Bytes zu 1 Million mit s = s + "stuff" ist extrem teuer. Wenn Sie nur 5 Bytes zum Ende schreiben und mit Ihrem Programm fortfahren möchten, dann müssen Sie eine Klasse auswählen, die etwas Raum für Wachstum lässt.

StringBuilder sb = new StringBuilder(5000); 
for (; ;) 
    { 
     sb.Append("stuff"); 
    } 

Stringbuilder wird auto-grow by doubling wenn es Grenze getroffen wird. So werden Sie den Wachstumsschmerz einmal beim Start sehen, einmal bei 5000 Bytes, wieder bei 10000, wieder bei 20000. Beim Anhängen von Strings treten bei jeder Schleifeniteration die Schmerzen auf.

+4

Es ist auch erwähnenswert, dass StringBuilder Sie die Anfangsgröße festlegen können. Nützlich, wenn Sie wissen, dass Sie im Voraus 10.000.000 Einträge verwenden werden, sodass Sie etwas von der Krise ignorieren können. –

+2

+1 Für das Durchschauen der Frage und das Beantworten des guten Designs. Im Vergleich dazu: "So groß ist Ihre Saite, bevor sie bläst", im Gegensatz zu "wenn Sie wirklich eine Menge Text speichern müssen, verwenden Sie dies ..." – StevoInco

5

Strings werden nicht durch ganzzahlige beschränkt, wie häufig

angenommen wird, Einschränkungen Speicher zur Seite, Strings können nicht mehr als 2 (1.073.741.824) Zeichen, da eine 2 GB Grenze von der Microsoft CLR (Common Language auferlegt wird Laufzeit).

Hoffentlich kann sich das in Zukunft ändern.

0

Beachten Sie, dass BinaryWriter.Write (Zeichenfolge) die Zeichenfolge Länge als ein Zeichen ohne Vorzeichen (ein Byte) schreibt!