Warum ist String in C # ein Referenztyp, der sich wie ein Werttyp verhält?
Ein String ist ein Referenztyp ist, obwohl es die meisten der Merkmale einer Wert-Typ wie Unveränderbarkeit und mit == überladen, zu vergleichen, den text, anstatt dass Sie sicher, dass Sie das gleiche Objekt referenzieren.
Warum ist string nur ein Wert geben Sie dann?
InformationsquelleAutor der Frage Davy8 | 2009-03-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Strings sind nicht Wert-Typen, da Sie riesig sein kann, und müssen gespeichert werden auf dem heap. Wert-Typen sind (in allen Implementierungen der CLR noch?) auf dem stack gespeichert werden. Stack-Zuweisung von strings brechen würde alle möglichen Dinge: der stack ist nur 1MB, müssten Sie die box jede saite, dass eine Kopie Strafe, Sie konnte es nicht intern Streicher und Speichernutzung würde, Ballon, etc...
(Edit: Hinzugefügt Aufklärung über Wert, Art der Lagerung wird eine Implementierung detail, das führt zu dieser situation, wo wir einen Typ mit dem Wert sematics nicht Erben von System.ValueType. Danke Ben.)
InformationsquelleAutor der Antwort codekaizen
Es ist nicht einen Wert geben, da die Leistung (Zeit und Raum!) wäre schrecklich, wenn es einen Wert-Typ und dessen Wert, die kopiert werden mussten jedes mal, wenn Sie übergeben wurden, zu und kehrte von Methoden, etc.
Es hat Wert-Semantik, die Welt zu halten sane. Können Sie sich vorstellen, wie schwierig es sein würde, um code, wenn
set
b
zufalse
? Sich vorstellen, wie schwierig Kodierung, gerade über jede mögliche Anwendung wäre.InformationsquelleAutor der Antwort jason
Die Unterscheidung zwischen Referenz-Typen und Wert-Typen sind im Grunde eine performance-Kompromiss in der Gestaltung der Sprache. Referenz-Typen haben einigen Aufwand auf den Bau, Zerstörung und garbage collection, weil Sie auf dem heap erstellt. Wert-Typen auf der anderen Seite haben overhead auf Methodenaufrufe (wenn die Größe der Daten größer als ein Zeiger), weil das ganze Objekt wird kopiert, anstatt nur einen Zeiger. Weil strings können (und werden normalerweise) viel größer als die Größe eines Zeigers, Sie sind konzipiert als Referenz-Typen. Auch, als Servy darauf hingewiesen, daß die Größe einen Wert geben muss, der zur Kompilierzeit bekannt, was nicht immer der Fall für Streicher.
Die Frage der Veränderlichkeit ist ein eigenes Thema. Sowohl Referenz-Typen und Wert-Typen können entweder veränderlich oder unveränderlich sein. Wert-Typen sind in der Regel unveränderlich obwohl, da die Semantik für veränderliche value-Typen kann verwirrend sein.
Referenz-Typen sind in der Regel änderbar, aber kann entworfen werden, als unveränderliche, ob es Sinn macht. Strings werden definiert als unveränderlich, weil es bestimmte Optimierungen möglich. Zum Beispiel, wenn der gleiche string-literal tritt mehrmals im gleichen Programm (das ist durchaus üblich), kann der compiler die Wiederverwendung der gleichen Objekt.
Warum also ist "==" überladen strings vergleichen von text? Da ist es nützlich, die meisten Semantik. Wenn zwei strings gleich sind, indem text, Sie können oder möglicherweise nicht das gleiche Objekt verweisen aufgrund der Optimierungen. So dass der Vergleich Verweise sind ziemlich nutzlos, beim Vergleich von text sind fast immer, was Sie wollen.
Sprechen generell Saiten hat, was wird als Wert-Semantik. Dies ist ein allgemeiner Begriff, als Wert-Typen, das ist ein C# - spezifische Implementierung detail. Wert-Typen haben Wert-Semantik, aber Referenz-Typen können auch Wert-Semantik. Wenn ein Typ, Wert-Semantik, kann man nicht wirklich sagen, ob die zugrunde liegende Implementierung ist ein Verweistyp oder ein Werttyp, so können Sie erwägen, dass eine Implementierung detail.
InformationsquelleAutor der Antwort JacquesB
Nicht nur Zeichenfolgen unveränderlich sind Referenz-Typen.
Multi-cast delegates zu.
Das ist, warum es ist sicher zu schreiben
Nehme ich an, dass strings unveränderlich sind, denn dies ist die sichere Methode, mit Ihnen zu arbeiten und Speicher.
Warum sind Sie nicht Wert-Typen? Vorherigen Autoren Recht über die stack-Größe, etc. Ich würde auch hinzufügen, dass strings eine Referenz-Typen zu ermöglichen, sparen bei der Montage auf die Größe, wenn Sie die gleiche string-Konstante im Programm. Wenn Sie definieren
Sind die Chancen, dass Sie beide Instanzen von "my string" - Konstante zugewiesen werden, in Ihre Versammlung nur einmal.
Wenn Sie möchten, zu verwalten Saiten wie üblich Referenz-Typ, legen Sie die Schnur in einem neuen StringBuilder(string s). Oder verwenden Sie MemoryStreams.
Wenn Sie zum erstellen einer Bibliothek, wo Sie erwarten eine große strings zu übergeben, in der Sie Ihre Funktionen, entweder definieren Sie einen parameter als ein StringBuilder oder als Stream.
InformationsquelleAutor der Antwort Bogdan_Ch
Dies ist eine späte Antwort auf eine alte Frage, aber alle anderen Antworten sind fehlt der Punkt, das ist, dass .NET nicht über Generika bis .NET 2.0 in 2005.
String
ist ein Referenz-Typ statt einen Wert geben, weil es war von entscheidender Bedeutung für Microsoft, um sicherzustellen, dass Zeichenfolgen gespeichert werden können, auf die effizienteste Weise in nicht-generischen collectionswieSystem.Collection.ArrayList
.Speichern ein Wert-Typ in eine nicht-generische collection ist eine spezielle Umstellung auf die Art
object
was wird als boxing bezeichnet. Wenn die CLR-Boxen einen Wert geben, er wickelt sich der Wert innerhalb einesSystem.Object
und speichert Sie auf dem verwalteten heap.Lesen den Wert von der Sammlung erfordert die inverse operation, das heißt unboxing.
Beide boxing und unboxing nicht-vernachlässigbaren Kosten: Boxen erfordert eine zusätzliche Zuweisung, unboxing erfordert die überprüfung von Typ.
Einige Antworten behaupten fälschlicherweise, dass
string
konnte nie umgesetzt wurden, als Wert geben, weil seine Größe ist variabel. Eigentlich ist es einfach zu implementieren-string eine Feste Länge von Daten-Struktur mit einem Kleinen String-Optimierung-Strategie: Zeichenfolgen im Speicher gespeichert, direkt als eine Sequenz von Unicode-Zeichen, außer für große Zeichenfolgen gespeichert werden würden als ein Zeiger auf eine externe Puffer. Beide Darstellungen können entworfen werden, um die gleiche Feste Länge, D. H. die Größe eines Zeigers.Wenn Generika bereits ab dem ersten Tag ich denke, dass string als Wert geben, wäre wahrscheinlich die bessere Lösung gewesen, mit einfacher Semantik, bessere Speichernutzung und bessere cache-Lokalität. Ein
List<string>
mit nur kleinen Streicher hätte ein einzelner zusammenhängender block im Speicher.InformationsquelleAutor der Antwort ZunTzu
Auch die Weise, wie strings implementiert sind (unterschiedlich für jede Plattform) und wenn Sie anfangen zu Nähen Sie zusammen. Wie mit einem
StringBuilder
. Es allocats einen Puffer für das kopieren in, wenn Sie erreichen das Ende, es weist auch mehr Speicher für Sie, in der Hoffnung, dass, wenn Sie tun eine große Verkettung Leistung nicht behindert werden.Vielleicht Jon Skeet helfen können, aus den hier?
InformationsquelleAutor der Antwort Chris
Es ist hauptsächlich ein performance-Problem.
Dass strings Verhalten sich WIE Werttyp hilft beim schreiben von code, aber dass es einen Wert geben würde einen enormen performance-hit.
Sich für eine in-depth look, nehmen Sie einen Blick auf eine netter Artikel auf Zeichenfolgen in der .net framework.
InformationsquelleAutor der Antwort Denis Troller
Wie können Sie sagen
string
ist eine Referenz geben? Ich bin mir nicht sicher, dass es darauf ankommt, wie es umgesetzt wird. Strings in C# sind unveränderlich genau, so dass Sie nicht haben, um sorgen über dieses Problem.InformationsquelleAutor der Antwort
Eigentlich Zeichenfolgen haben sehr wenige ähnlichkeiten mit Wert-Typen. Für den Anfang nicht allen Wert-Typen sind unveränderlich, Sie können ändern Sie den Wert für einen Int32-alles, was Sie wollen, und es wäre immer noch die gleiche Adresse auf den stack.
Zeichenfolgen unveränderlich sind, für einen sehr guten Grund, es hat nichts damit zu tun, dass es ein Referenz-Typ, hat aber eine Menge zu tun mit memory-management. Es ist einfach effizienter ein neues Objekt zu erstellen, wenn die Zeichenfolge, die Größe ändert sich, als zu verschieben Dinge um die auf dem verwalteten heap. Ich denke, Sie mischen zusammen mit dem Wert/Referenz, Datentypen und immutable Objekte-Konzepte.
Soweit "==",: Wie Sie sagte, "= = " ist ein operator überladen, und es war wieder umgesetzt, für einen sehr guten Grund, um Rahmen mehr nützlich bei der Arbeit mit Zeichenfolgen.
InformationsquelleAutor der Antwort WebMatrix
Ist nicht so einfach wie Strings sind Zeichen-arrays. Ich schaue auf strings als Zeichen-arrays[]. Deshalb werden Sie auf dem heap, da der Verweis Speicherstelle auf dem stack gespeichert werden und die Punkte an den Anfang des Arrays Speicher auf dem heap. Die Größe der Zeichenfolge nicht bekannt ist, bevor es zugewiesen wird ...perfekt für den heap.
Deshalb ein string ist wirklich unveränderlich, weil, wenn Sie es ändern, auch wenn es von der gleichen Größe, die der compiler nicht weiß, dass und zuordnen muss ein neues array und weisen Zeichen an der Position im array. Es macht Sinn, wenn Sie denken, dass strings als eine Möglichkeit, die Sprachen zu schützen, müssen Sie Speicher on-the-fly (Lesen, C-ähnliche Programmiersprache)
InformationsquelleAutor der Antwort BionicCyborg
In einem sehr einfachen Worten einen beliebigen Wert, der hat eine bestimmte Größe behandelt werden kann, als ein Wert-Typ.
InformationsquelleAutor der Antwort saurav.net
Auf die Gefahr, sich noch eine andere geheimnisvolle down-vote...die Tatsache, dass viele erwähnen den stack und Speicher mit Bezug auf Wertetypen und primitiven Typen ist, denn Sie müssen sich in ein register in dem Mikroprozessor. Sie können push-oder pop-etwas zum/vom Stapel, wenn es braucht mehr bits als ein register hat....die Anweisungen sind, zum Beispiel "pop eax" - weil eax 32 bit auf einem 32-bit-system.
Floating-point primitive Typen behandelt werden, die von der FPU, die 80 bit breit.
Das alles war entschieden, lange bevor es war eine OOP-Sprache zu verschleiern die definition der primitiv-Typ, und ich gehe davon aus, dass der Wert, der Typ ist ein Begriff, der geschaffen hat, die speziell für OOP Sprachen.
InformationsquelleAutor der Antwort jinzai