Frage

Ein String ist ein Referenz-Typ, obwohl es die meisten der Eigenschaften eines Werttypen wie seine unveränderlich ist und == den Text zu vergleichen überlastet hat, anstatt dafür, dass sie das gleiche Objekt verweisen.

Warum String wird nicht nur ein Wert geben Sie dann?

War es hilfreich?

Lösung

Strings sind nicht Werttypen, da sie sehr groß sein können, und müssen auf dem Heap gespeichert werden. Werttypen sind (in allen Implementierungen des CLR als die noch) auf dem Stapel abgelegt. Stack Strings Zuweisung würde alle möglichen Dinge brechen: der Stapel nur 1 MB für 32-Bit- und 4 MB für 64-Bit ist, müssten Sie jede Zeichenfolge boxen, eine Kopie Vertragsstrafe zahlen, könnten Sie nicht intern Strings und Speichernutzung würde der Ballon, etc ...

(Edit:.. Hinzugefügt Klärung über Werttyp Speicher eine Implementierung Detail zu sein, die zu dieser Situation führt, wo wir einen Typ mit dem Wert sematics haben nicht von System.ValueType vererben Dank Ben)

Andere Tipps

Es ist kein Werttyp, da die Leistung (Raum und Zeit!) Wäre schrecklich, wenn es sich um ein Werttyp und dessen Wert waren musste jedes Mal kopiert werden, um sie übergeben wurden und kehrte von Methoden, etc.

Es hat einen Wert Semantik, die Welt gesund zu halten. Können Sie sich vorstellen, wie schwierig es zu codieren wäre, wenn

string s = "hello";
string t = "hello";
bool b = (s == t);

set b werden false? Stellen Sie sich vor, wie schwierig Codierung fast jede Anwendung wäre.

Die Unterscheidung zwischen Referenztypen und Werttypen sind im Prinzip in der Gestaltung der Sprache eine Leistung Kompromiss. Referenztypen haben einige Overhead auf Konstruktion und Destruktion und Müllabfuhr, weil sie auf dem Heap erstellt werden. Werttypen auf der anderen Seite haben Overhead auf Methodenaufrufe (wenn die Datengröße größer als ein Zeiger), da das gesamte Objekt kopiert wird, anstatt nur einen Zeiger. Da Strings sein kann (und in der Regel ist) viel größer als die Größe eines Zeigers, werden sie als Referenztyp ausgelegt. Auch als Servy wies darauf hin, die Größe eines Werttypen muss zum Zeitpunkt der Kompilierung bekannt sein, was nicht immer der Fall für Strings ist.

Die Frage der Veränderlichkeit ist ein anderes Thema. Beiden Referenztypen und Werttypen können entweder wandelbar oder unveränderlich sein. Werttypen sind in der Regel unveränderlich obwohl, da die Semantik für wandelbare Werttypen kann verwirrend sein.

Referenztypen sind in der Regel wandelbar, können aber als unveränderlich gestaltet werden, wenn es Sinn macht. Strings werden als unveränderlich definiert, weil es bestimmte Optimierungen möglich macht. Zum Beispiel tritt auf, wenn die gleiche Stringliteral mehrmals im gleichen Programm (das ist durchaus üblich), kann der Compiler das gleiche Objekt wiederverwendet werden.

Also, warum ist „==“ überlastet Strings von Text zu vergleichen? Da es sich um die nützlichsten Semantik. Wenn zwei Strings von Text gleich sind, können sie oder können nicht das gleiche Objekt Bezug auf die Optimierungen zurückzuführen sein. So Vergleich Referenzen sind ziemlich nutzlos, während Text zu vergleichen sind fast immer das, was Sie wollen.

allgemeiner gesprochen, hat Strings, was bezeichnet wird Wert Semantik . Dies ist ein allgemeiner Begriff als Werttypen, die ein C # spezifische Implementierung Detail. Werttypen haben Wert Semantik, sondern Referenztypen können auch Wert Semantik haben. Wenn ein Typ Wert Semantik hat, kann man nicht wirklich sagen, ob die zugrunde liegende Implementierung ein Referenztyp oder Werttyp ist, so können Sie, dass eine Implementierung Detail betrachten.

Dies ist eine späte Antwort auf eine alte Frage, aber alle andere Antworten fehlen den Punkt, das ist, dass .NET nicht Generika bis .NET 2.0 im Jahr 2005 hat.

String ist ein Referenz-Typ anstelle eines Werttyp, weil war es von entscheidender Bedeutung für Microsoft, um sicherzustellen, dass Strings auf die effizienteste Art und Weise in nicht-generischen Sammlungen , wie System.Collection.ArrayList gespeichert werden könnten.

Wert-Typ in einer nicht-generische Auflistung speichern erfordert eine spezielle Umwandlung der Art object die Boxen genannt wird. Wenn die CLR-Boxen ein Werttyp, wickelt sie den Wert in einem System.Object und speichert sie auf dem verwalteten Heap.

den Wert aus der Sammlung Lesen erfordert die umgekehrte Operation, die Unboxing genannt wird.

Beide Boxen und Unboxing haben nicht zu vernachlässigenden Kosten. Boxen erfordert eine zusätzliche Zuweisung, Unboxing erfordert Typprüfung

Anspruch Einige Antworten falsch, dass string nie als Werttyp umgesetzt worden sein könnte, weil seine Größe variabel ist. Eigentlich ist es einfach String als feste Länge Datenstruktur zu implementieren Strategie mit einer kleinen String-Optimierung: Strings im Speicher abgelegt werden würden direkt als Folge von Unicode-Zeichen außer für große Zeichenfolge, die als Zeiger auf einen externen Puffer gespeichert werden würden. Beide Darstellungen können so gestaltet werden, um die gleiche feste Länge haben, das heißt, die Größe eines Zeigers.

Wenn Generika von Tag bestanden hatte, den ich denke, String als Wert Typs wäre wahrscheinlich eine bessere Lösung gewesen, mit einfacheren Semantik, eine bessere Speichernutzung und eine bessere Cache-Lokalität. Ein List<string> nur kleine Zeichenfolge mit einem einzigen zusammenhängenden Speicherblock hätte sein können.

Nicht nur Strings sind unveränderlich Referenztypen. Multi-Cast Delegierten zu. Deshalb ist es sicher zu schreiben

protected void OnMyEventHandler()
{
     delegate handler = this.MyEventHandler;
     if (null != handler)
     {
        handler(this, new EventArgs());
     }
}

Ich nehme an, dass Strings unveränderlich sind, weil dies die sicherste Methode ist, mit ihnen zu arbeiten und Speicher zuweisen. Warum sind sie nicht Werttypen? Zurück Autoren haben Recht über Stackgröße etc. Ich auch, dass die Herstellung Strings eine Referenz hinzufügen würde Typen ermöglichen bei der Montage Größe zu speichern, wenn Sie das gleiche konstante String im Programm verwenden. Wenn Sie definieren

string s1 = "my string";
//some code here
string s2 = "my string";

Die Chancen stehen gut, dass beide Instanzen von „meine Zeichenfolge“ Konstante nur einmal in Ihrer Assembly zugewiesen werden.

Wenn Sie möchten, dass Zeichenketten wie üblich Referenztyp verwalten, legen Sie die Zeichenfolge in einem neuen String (string s). Oder MemoryStreams verwenden.

Wenn Sie eine Bibliothek erstellen, wo Du eine große Strings erwarten in Ihren Funktionen übergeben werden, entweder definieren einen Parameter als String oder als Stream übertragen.

Auch werden die Art und Weise Strings (unterschiedlich für jede Plattform) implementiert und wenn Sie beginnen sie zusammen nähen. Wie ein StringBuilder verwenden. Es allocats einen Puffer für Sie kopieren in, sobald Sie das Ende erreichen, ist es für Sie noch mehr Speicher reserviert, in der Hoffnung, dass, wenn Sie eine große Verkettung Leistung tun wird nicht behindert werden.

Vielleicht Jon Skeet kann hier draußen aufhelfen?

Es ist in erster Linie ein Leistungsproblem.

Mit verhaltenen Strings wie Werttyp hilft beim Schreiben von Code, sondern mit ihm ein Werttyp sein würde, eine großen Leistungseinbußen machen.

Für einen eingehenden Blick, werfen Sie einen Blick auf einem schöne Artikel rel="nofollow auf Strings in .NET Framework.

Wie kann man sagen, string ist ein Referenztyp? Ich bin nicht sicher, dass es wichtig ist, wie es umgesetzt wird. Streicher in C # sind genau unveränderlich, so dass Sie sich nicht um dieses Problem zu kümmern.

Eigentlich haben Strings sehr wenige Ähnlichkeiten zu Werttypen. Für den Anfang nicht alle Werttypen sind unveränderlich, können Sie den Wert eines Int32 ändern alles, was Sie wollen, und es wäre es immer noch die gleiche Adresse auf dem Stapel sein.

Strings sind unveränderlich für einen sehr guten Grund, es hat nichts damit ein Referenztyp sein, aber viel mit der Speicherverwaltung zu tun hat, zu tun hat. Es ist nur effizienter, ein neues Objekt zu erstellen, wenn String Größenänderungen als die Dinge auf dem verwalteten Heap zu verschieben um. Ich glaube, Sie Mischen Wert / Referenztypen und unveränderliche Objekte Konzepte.

Was „==“. Wie gesagt, du „==“ ein Operator Überlastung und es wieder für einen sehr guten Grund, umgesetzt wurde, um Rahmen nützlicher, wenn Arbeiten mit Zeichenkette

In einem sehr einfachen Worten jeder Wert, der eine bestimmte Größe hat, kann als Werttyp behandelt werden.

Ist das nicht so einfach wie Strings aus Zeichen-Arrays hergestellt werden. Ich sehe Strings als Zeichen-Arrays []. Daher sind sie auf dem Heap, weil die Bezugs-Speicherposition auf dem Stapel und zeigt auf den Anfang des Arrays des Speicherplatz auf dem Heap gespeichert ist. Die Stringgröße ist nicht bekannt, bevor er zugeordnet ist ... perfekt für den Haufen.

Deshalb ist ein String wirklich unveränderlich ist, weil, wenn Sie es ändern, selbst wenn sie von der gleichen Größe ist der Compiler das nicht weiß und hat ein neues Array zuweisen und Zeichen in der Anordnung den Positionen zuordnen. Es macht Sinn, wenn man von Strings als eine Möglichkeit denken, die Sprachen, die Sie schützen aus dem Speicher im laufenden Betrieb (lesen C wie Programmierung)

zuzuteilen mit

Auf der Gefahr immer noch einen weitere mysteriöse Abwärts Stimme ... die Tatsache, dass viele die Stapel und Speicher in Bezug auf Werttypen und primitive Typen erwähnen ist, weil sie in ein Register in dem Mikroprozessor passen muss. Sie können nicht schieben oder Pop, etwas zu / von dem Stapel, wenn es mehr Bits als ein Register hat nimmt .... die Anweisungen sind, zum Beispiel „pop eax.“ - weil eax ist 32 Bit breit auf einem 32-Bit-System

Gleitkommaoperationen primitive Typen werden von der FPU behandelt, die 80 Bit breit ist.

Das war alles längst entschieden, bevor es eine OOP-Sprache war die Definition des Urtyps zu verschleiern und ich nehme an, dass Werttyp ist ein Begriff, der speziell für die OOP-Sprachen erstellt wurde.

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