Huch, diese Antwort wurde akzeptiert und dann habe ich sie geändert. Ich sollte wahrscheinlich die ursprüngliche Antwort an den unteren Rand einfügen, da dies vom OP akzeptiert wurde.
Aktualisieren : Hier ist die Sache. string
absolut muss sich wie ein Referenztyp verhalten . Die Gründe dafür wurden bisher von allen Antworten berührt: Der string
-Typ hat keine konstante Größe, es macht keinen Sinn, den gesamten Inhalt einer Zeichenkette von einer Methode in eine andere zu kopieren, sonst würden string[]
-Arrays muss die Größe von themelves ändern - um nur einige zu nennen.
Aber Sie könnten definieren string
als struct
, das intern auf ein char[]
-Array verweist, oder sogar einen char*
-Zeiger und ein int
für seine Länge, machen Sie es unveränderlich, und voila! , Sie hätten einen Typ, der sich wie ein Referenztyp verhält, aber technisch ein Werttyp ist.
Das wäre ziemlich albern, ehrlich gesagt. Wie Eric Lippert in einigen der Kommentare zu anderen Antworten darauf hingewiesen hat, ist die Definition eines solchen Werttyps im Grunde dasselbe wie die Definition eines Referenztyps. In fast jeder Hinsicht wäre es von einem auf die gleiche Weise definierten Referenztyp nicht zu unterscheiden.
Also die Antwort auf die Frage "Warum ist string
ein Referenztyp?" ist im Grunde genommen: "Es Wert zu machen wäre einfach albern." Aber wenn das der einzige Grund ist, dann ist die logische Schlussfolgerung, dass string
tatsächlich wie oben beschrieben als struct
definiert werden konnte und es kein besonders gutes Argument gegen diese Wahl geben würde.
Allerdings sind Gründe, dass es besser ist, string
a class
als% struct
zu machen, die mehr als rein intellektuell sind. Hier sind ein Paar, an das ich denken konnte:
Wenn string
ein Werttyp wäre, dann müsste jedes Mal, wenn Sie es an eine Methode übergeben haben, die object
erwartet, ein neues object
erzeugt werden, wodurch der Heap aufgebläht würde und sinnlos wäre GC-Druck. Da Strings im Prinzip überall sind , wäre es ein großes Problem, sie zu haben, wenn man sie ständig boxt.
Ja, string
kann Equals
überschreiben, unabhängig davon, ob es sich um einen Referenztyp oder -typ handelt. Aber wenn es ein Werttyp wäre, dann würde ReferenceEquals("a", "a")
false zurückgeben! Dies liegt daran, dass beide Argumente eingerahmt und die Argumente mit Box nie erhalten würden habe gleiche Referenzen (soweit ich weiß).
Auch wenn es wahr ist, dass Sie einen Wertetyp definieren könnten, um genau wie einen Referenztyp zu verwenden, indem er aus einem einzelnen Referenztypfeld besteht, wäre es immer noch nicht genau das gleiche. Also behalte ich dies als den vollständigeren Grund, warum string
ein Referenztyp ist: Sie könnten es zu einem Werttyp machen, aber dies würde es nur mit unnötigen Schwächen belasten.
Es ist ein Referenztyp, weil nur Referenzen darauf herumgereicht werden.
Wenn es ein Werttyp wäre, dann würde jedes Mal, wenn Sie eine Zeichenfolge von einer Methode zu einer anderen übergeben, die gesamte Zeichenfolge kopiert werden *.
Da es ein Referenztyp ist, anstelle von String-Werten wie "Hallo Welt!" herumgereicht werden - "Hallo Welt!" ist übrigens 12 Zeichen, was bedeutet, dass es (mindestens) 24 Bytes Speicher benötigt - nur Referenzen zu diesen Strings werden weitergegeben. Das Übergeben einer Referenz ist viel billiger als das Übergeben jedes einzelnen Zeichens in einer Zeichenfolge.
Außerdem ist es wirklich nicht ein normaler primitiver Datentyp. Wer hat dir das gesagt?
* Eigentlich ist das nicht genau richtig. Wenn die Zeichenfolge intern ein char[]
-Array enthält, wird der Inhalt der Zeichenfolge, solange der Array-Typ ein Referenztyp ist, tatsächlich nicht als Wert übergeben - nur der Verweis auf das Array wäre. Ich denke immer noch, dass dies im Grunde die richtige Antwort ist.
Zusätzlich zu den Gründen von Dan:
Werttypen sind nach Definition solche Typen, die ihre Werte in sich selbst speichern, anstatt auf einen Wert anderswo zu verweisen. Deshalb werden Werttypen als "Werttypen" und Referenztypen als "Referenztypen" bezeichnet. Also ist Ihre Frage wirklich "Warum bezieht sich eine Zeichenkette auf ihren Inhalt und nicht einfach auf mit Inhalt?"
Das liegt daran, dass Werttypen die nette Eigenschaft haben, dass jede Instanz eines bestimmten Werttyps dieselbe Größe im Speicher hat.
Na und? Warum ist das eine schöne Eigenschaft? Angenommen, Zeichenfolgen waren Werttypen, die eine beliebige Größe haben könnten, und berücksichtigen Folgendes:
%Vor%Was sind die ursprünglichen Inhalte dieses Arrays aus drei Strings? Für Werttypen gibt es kein "Null". Daher ist es sinnvoll, ein Array aus drei leeren Strings zu erstellen. Wie würde das in Erinnerung bleiben? Denken Sie ein bisschen darüber nach. Wie würdest du es tun?
Nehmen wir an, Sie sagen
%Vor%Jetzt haben wir "", "Hallo" und "" im Array. Wo im Speicher ist das "Hallo"? Wie groß ist der Slot, der für mistrings [1] vergeben wurde? Der Speicher für das Array und seine Elemente muss irgendwo sein.
Damit bleibt der CLR die folgende Auswahl:
Das CLR-Team wählte das letztere. Wenn Sie Strings zu Referenztypen machen, können Sie Arrays effizient erstellen.
String ist ein Referenztyp, kein Werttyp. In vielen Fällen kennen Sie die Länge der Zeichenfolge und den Inhalt der Zeichenfolge. In solchen Fällen ist es einfach, den Speicher für die Zeichenfolge zuzuordnen. aber bedenke so etwas.
%Vor%ist es nicht möglich, die Zuordnungsdetails für "s" in der Kompilierungszeit zu kennen. Der Benutzer gibt die Werte ein und alle eingegebenen Zeichenfolgen / Zeilen werden in den s gespeichert. Daher werden Zeichenfolgen im Heapspeicher gespeichert, sodass der Speicher neu zugewiesen wird, damit er in den Inhalt der Zeichenfolge s passt. Und der Verweis auf diese Zeichenfolge wird im Stapel gespeichert.
Um mehr zu erfahren, lesen Sie bitte: .net zero by petzold
Lesen: Garbage Collection von CLR Via C # für Zuordnungsdetails auf Stapel.
Bearbeiten: Console.WriteLine (); zu Console.ReadLine ();
Tags und Links string c# reference-type primitive-types