Heute habe ich bemerkt, dass die String-Klasse von C # die Länge einer Zeichenkette als Int zurückgibt. Da ein Int immer 32 Bits lang ist, bedeutet dies, unabhängig von der Architektur, dass ein String nur 2 GB oder weniger lang sein kann?
Eine 2GB-Zeichenfolge wäre sehr ungewöhnlich und würde viele Probleme mit sich bringen. Die meisten .NET-APIs verwenden jedoch "int", um Werte wie Länge und Anzahl zu übermitteln. Bedeutet dies, dass wir für immer auf die Größe von Sammlungen beschränkt sind, die in 32-Bit passen?
Scheint wie ein grundlegendes Problem mit den .NET-APIs. Ich hätte erwartet, dass Dinge wie Anzahl und Länge über das Äquivalent von 'size_t' zurückgegeben werden.
Scheint wie ein grundlegendes Problem mit die .NET API ...
Ich weiß nicht, ob ich so weit gehen würde.
Betrachten Sie fast jede Auflistungsklasse in .NET. Wahrscheinlich ist es eine Count
-Eigenschaft, die eine int
zurückgibt. Dies legt nahe, dass die Klasse in einer Größe von int.MaxValue
(2147483647) begrenzt ist. Das ist nicht wirklich ein Problem ; Es ist eine Einschränkung - und eine durchaus vernünftige, in der überwiegenden Mehrheit der Szenarien.
Wie auch immer, was wäre die Alternative? Es gibt uint
- aber das ist nicht CLS-konform. Dann gibt es long
...
Was ist, wenn Length
eine long
zurückgegeben hat?
Stellen Sie sich die unglaublichen Kosten eines solchen Codes vor:
%Vor% Grundsätzlich, wenn Sie an string
als eine Datenstruktur denken, die eine unbegrenzte Menge an Text speichern soll, haben Sie unrealistische Erwartungen. Bei Objekten dieser Größe wird es fraglich, ob Sie sie überhaupt im Speicher halten müssen (im Gegensatz zur Festplatte).
Korrigieren Sie, die maximale Länge wäre die Größe von Int32, aber Sie werden wahrscheinlich zu anderen Speicherproblemen kommen, wenn Sie mit Strings arbeiten, die sowieso größer sind.
Bei einem Wert von String.length () von etwa 5MB ist es nicht wirklich praktisch, String zu verwenden. String ist für kurze Textabschnitte optimiert.
Denken Sie darüber nach, was passiert, wenn Sie es tun
%Vor%Etwas wie:
System berechnet die Länge von myString plus die Länge von "more chars"
System weist diese Speichermenge zu
System kopiert myString an einen neuen Speicherort
Das System kopiert "mehr Zeichen" nach dem letzten kopierten myString char in den neuen Speicherbereich
Der ursprüngliche myString ist der Gnade des Garbage Collectors überlassen.
Während das für kleine Textabschnitte nett und ordentlich ist, ist es ein Albtraum für große Strings, nur 2 GB zusammenhängender Speicher zu finden ist wahrscheinlich ein Showstopper.
Wenn Sie also wissen, dass Sie mehr als ein paar MB an Zeichen verarbeiten, verwenden Sie eine der * Buffer-Klassen.
Es ist ziemlich unwahrscheinlich, dass Sie mehr als zwei Milliarden Objekte in einer einzelnen Sammlung speichern müssen. Sie werden einige ziemlich schwerwiegende Leistungseinbußen erleiden, wenn Sie Aufzählungen und Nachschlagevorgänge durchführen, die die beiden Hauptziele von Sammlungen sind. Wenn Sie mit einem so großen Datensatz arbeiten, gibt es fast sicher eine andere Route, die Sie verwenden können, z. B. die Aufteilung Ihrer einzelnen Sammlung in viele kleinere Sammlungen, die Teile der gesamten Datenmenge enthalten, mit der Sie arbeiten.
Heeeey, warte eine Sekunde ... wir haben schon dieses Konzept - es heißt ein Wörterbuch !
Wenn Sie beispielsweise 5 Milliarden englische Zeichenfolgen speichern müssen, verwenden Sie diesen Typ:
%Vor%Nehmen wir an, dass die Schlüsselzeichenfolge die ersten beiden Zeichen der Zeichenfolge repräsentiert. Dann schreibe eine Erweiterungsmethode wie folgt:
%Vor%und fügen Sie dann Elemente zu bigStringContainer wie folgt hinzu:
%Vor%und nenne es einen Tag. (Es gibt offensichtlich effizientere Möglichkeiten, dies zu tun, aber dies ist nur ein Beispiel)
Oh, und wenn Sie wirklich wirklich in der Lage sein müssen, ein beliebiges Objekt nach dem absoluten Index zu suchen, verwenden Sie Array
anstelle einer Sammlung. Okay, yeah, du verwendest eine Art Sicherheit, aber du kannst Array-Elemente mit einem long
indexieren.
Die Tatsache, dass das Framework Int32
für Count
/ Length
Eigenschaften, Indexer usw. verwendet, ist ein bisschen wie ein Ablenkungsmanöver. Das eigentliche Problem ist, dass die CLR derzeit eine maximale Objektgrößenbeschränkung von 2 GB hat.
So kann ein string
- oder jedes andere einzelne Objekt - niemals größer als 2GB sein.
Das Ändern der Eigenschaft Length
des Typs string
, um long
, ulong
oder sogar BigInteger
zurückzugeben, wäre sinnlos, da Sie niemals mehr als ca. 2 ^ 30 Zeichen haben könnten (max. 2 GB und 2 Bytes pro Zeichen.)
Auch wegen der Begrenzung von 2 GB wären die einzigen Arrays, die sogar 2 ^ 31 Elemente haben könnten, bool[]
oder byte[]
Arrays, die nur 1 Byte pro Element verwenden.
Natürlich gibt es nichts, was Sie daran hindert, eigene Composite-Typen zu erstellen, um die Beschränkung von 2 GB zu umgehen.
(Beachten Sie, dass die obigen Ausführungen für die aktuelle Implementierung von Microsoft gelten und sich in zukünftigen Versionen sehr wohl ändern könnten. Ich bin mir nicht sicher, ob Mono ähnliche Grenzen hat.)
In Versionen von .NET vor 4.5 beträgt die maximale Objektgröße 2 GB. Ab 4.5 können Sie größere Objekte zuweisen, wenn gcAllowVeryLargeObjects aktiviert ist . Beachten Sie, dass das Limit für string
nicht betroffen ist, aber "Arrays" sollten auch "Listen" abdecken, da Listen von Arrays unterstützt werden.
Selbst in x64-Versionen von Windows wurde ich von .Net getroffen, die jedes Objekt auf 2GB beschränkten.
2GB ist ziemlich klein für ein medizinisches Bild. 2GB ist sogar klein für ein Visual Studio-Download-Image.
Wenn Sie mit einer Datei mit 2 GB arbeiten, bedeutet dies, dass Sie wahrscheinlich viel RAM verwenden werden und die Leistung sehr langsam ist.
Verwenden Sie stattdessen für sehr große Dateien eine MemoryMappedFile (siehe: Ссылка ). Mit dieser Methode können Sie mit einer Datei von nahezu unbegrenzter Größe arbeiten, ohne das Ganze im Speicher zu laden.
Tags und Links string .net c# visual-studio